线程同步控制主要通过: synchronized wait() notify() notifyAll(); 关键字syschronized 是对每个对象都有一把锁,当有多个线程同时访问共享资源的时候,需要syschronized 来控制安全性。 syschronized 方法和syschronized 块,使用syschronized 块时候,一定要显示的获得该对象(syschronize(object))而方法则不需要。 java的内存模型是对每个进程有一个主内存,每个线程有自己的内存,他们从主内存中取数据,然后计算,再存入主内存。 Q.并发问题如下:如果多个线程同事操作同一数据, A线程从主内存中取的I的值为1, 然后进行加1操作, 这时B线程也取I的值, 进行加2操作, 然后A存入2到主内存中, B也存入, 这样就覆盖了A的值(同数据库中的并发问题一样)。 A.解决办法是用synchronize, 如用synchronized(I)。被synchronize 修饰的方法(块)把以下三步操作当成一个原子操作:取数据, 操作数据, 存数据。 我们知道原子操作是不可以被打断的, 所以其保证了数据一致性, 这样同一时间只有一个线程再执行, 对性能有一定的影响。这也是synchronize的第二个作用:保证统一时间只有一个线程再运行。 当实现SOCKET连接的时候经常用到. JAVA中规定非float long的原始类型的取和存操作作为原子操作。其实是对一个字(32位)的取,存位原始操作,因为 float long为2个字节长度,所以取,存位非原子操作。如果想把他们做为原子操作,则用 : valatile关键字修饰。 同步方法: public syschronized void change() { } 同步语句:(因为效率问题,有时考虑使用同步语句块) public void change() { Synchronized(this) {} } 有时候我们想让一段代码同步,可能与当前对象没有什么关系,可以自定义同步锁: private byte[] lock = new byte[1]; public void change() { Synchronized(lock){} } 自定义锁要注意: 1. private ,防止在类外部应用改变。 2. 如果可能用到,重写get方法,返回对象的clone ,而不是本身。 其他方法: Synchronized可以作用static,class. Class Foo { public synchronizedstatic void methodAAA()// 同步的static 函数{ //…. } public void methodBBB(){ synchronized(Foo.class)// class literal(类名称字面常量) } } 2.wait()/notify()/notifyAll() 在synchronized代码被执行期间,线程可以调用对象的wait()方法,释放对象锁标志,进入等待状态,并且可以调用notify()或者 notifyAll()方法通知正在等待的其他线程。notify()通知等待队列中的第一个线程,notifyAll()通知的是等待队列中的所有线程 public class PrintNum { private byte[] lock = new byte[0]; //自定义锁对象,这样代价最小,也可已使用当前对象this public void demo() { PrintThread a = new PrintThread("a"); PrintThread b = new PrintThread("b"); a.start(); b.start(); } class PrintThread extends Thread { public PrintThread(String name) { this.setName(name); } public void run() { synchronized(lock) { for(int i =0; i < 100; i++) { if(i % 10 == 0 && 0 != i) { try { lock.wait(); //暂时释放资源 lock.notify(); //唤醒另外一个进程 } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(this.getName()+": "+i); } } } } } 这个程序最终会因为互相唤醒而死锁,请你解决!