疯狂java


您现在的位置: 疯狂软件 >> 新闻资讯 >> 正文

Java多线程同步


 

  多线程在同时运行的时候,执行的先后次序是无法确定的,如果这些线程同时操作某个公共的资源,最终的执行结果是不可预测的,所以要在代码中采取某些方法来保护公共资源,保证同一时刻只允许一个线程访问这些资源。

  线程同步机制:

  1、多线程的同步依靠的是对象锁机制,synchronized关键字的背后就是利用了封锁来实现对共享资源的互斥访问。

  2、对象的互斥锁,能保证共享数据操作的完整性。每个对象都对应于一个可称为“互斥锁”的标记,这个标记保证在任一时刻,只能有一个线程访问该对象。

  3、Java中的线程同步是通过获取对象monitor来完成的,每个对象实例都有一个monitor。我们可以把这个monitor看成一把锁,线程在执行同步操作之前首先会针对对象实例执行锁定操作,也就是访问某个对象的synchronized方法,此时其他线程都无法再访问该synchronized方法了。

  4、同步代码执行完毕,则将monitor释放,此时若有其他线程要执行同样的操作,在获取对象monitor的时候也会阻塞等待,直到前面的线程将monitor释放位置。JVM保证同一时刻只有一个线程可以获得某个对象monitor。

  举例:

  [java]

  public class Test implements Runnable{

  public synchronized void run(){

  for(int i = 0;i < 10; i++){

  System.out.print(" " + i);

  }

  }

  public static void main(String[] args){

  Test t = new Test();

  Thread t1 = new Thread(t);

  Thread t2 = new Thread(t);

  t1.start();

  t2.start();

  }

  }

  如果不加锁,实现效果如下:00112345678923456789

  加锁,实现效果如下:01234567890123456789而且不论运行多少次,运行结果都是0-9。

  同步还有以下几种实现方法:

  Wait():使一个线程处于等待状态,并且释放所持有的对象的锁。

  Sleep():使一个正在运行的线程处于睡眠状态,使一个静态方法,调用此方法要捕捉

  InterruptedException异常。

  Join():用于等待另一个线程结束。

  Notify():唤醒一个处于等待状态的线程。在调用这个方法的时候并不能确切唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。

  AllNotify():唤醒所有处于等待状态的线程,注意并不是给所有唤醒线程一个对象的锁,而是让他们竞争。

  总结:

  需要注意的是,无论synchronized关键字夹在方法上还是对象上,他取得的锁都是对象,而不是一段代码或函数。同步是一种高开销的操作,应尽量减少需要同步的内容。