synchronized能够修饰代码块也能够修饰方法,还能够做用于静态方法,类和某个实例。java
每一个对象都有一把锁,当多个线程同时访问共享资源的时候,须要用到synchronized,synchronized分为代码块和方法,代码块须要显示的指定对象,而方法不须要(即当前对象)。ide
java的内存模型是对每个进程都有主内存,每一个线程也有本身的内存,它们从主内存中取数据,而后在计算,在存入主内存。函数
例子:如今有两个线程A,B线程,A线程对变量i加1,B线程同时对i加2,这两个线程同时操做,若是没有同步处理则B线程作的操做会覆盖A线程的操做。this
这时能够用synchronized处理,synchronized具备原子性,原子操做:取数据,操做数据,存数据。synchronized能够保证同一时间只有一个线程操做该对象。spa
java中对非Long和Float原始数据类型的存,取为原子操做。其实就是对一个字节的存,取操做,因为Float和Long为两个字节,因此其取,存为非原子操做。若是想把他们变成原子操做能够用volatile.线程
做用区域主要有两种:code
(1)、方法对象
(2)、代码块进程
对于用一对像的同步操做只能有一个线程,而对于不一样对象是互不干扰的。
内存
Public synchronized void change() { //同步方法 } Public void change() { Synchronized(this) { //同步语句:(由于效率问题,有时考虑使用同步语句块) } }
同步方法是针对当前对象的,若是不针对当前对象,而是针对其余对象能够用同步语句,如:
private byte[] lock= new byte[0]; Public void change() { Synchronized(lock) { } }
自定义锁注意:
a、对象必须为private防止其余类对象访问
b、geter方法最好clone一个对象返回
其余用法
能够针对静态方法和类
Class Foo { public synchronizedstatic void methodAAA()// 同步的static 函数 { //…. } public void methodBBB() { synchronized(Foo.class) // class literal(类名称字面常量) } }
它是针对整个类的,因此只能是同一个类的一个线程进行访问
synchronized(this)与synchronized(static class)的区别:
synchronized就是针对内存区块申请内存锁,this是类的一个对象,也就是针对相同对象的互斥操做,其余线程能够访问该类的其余对象。static是针对类,static是整个类共有的,也就是该类的全部成员间互斥。在同一时间只有一个线程能够访问该类的实例。
创建三个线程,A线程打印10次A,B线程打印10次B,C线程打印10次C,要求线程同时运行,交替打印10次ABC。这个问题用Object的wait(),notify()就能够很方便的解决。代码以下:
public class MyThreadPrinter2 implements Runnable { private String name; private Object prev; private Object self; private MyThreadPrinter2(String name, Object prev, Object self) { this.name = name; this.prev = prev; this.self = self; } @Override public void run() { int count = 10; while (count > 0) { synchronized (prev) { synchronized (self) { System.out.print(name); count--; self.notify(); } try { prev.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } } } public static void main(String[] args) throws Exception { Object a = new Object(); Object b = new Object(); Object c = new Object(); MyThreadPrinter2 pa = new MyThreadPrinter2("A", c, a); MyThreadPrinter2 pb = new MyThreadPrinter2("B", a, b); MyThreadPrinter2 pc = new MyThreadPrinter2("C", b, c); new Thread(pa).start(); new Thread(pb).start(); new Thread(pc).start(); } }