Java华丽转身 —— 多线程(二)——同步

来源:互联网 发布:经度纬度查询软件 编辑:程序博客网 时间:2024/06/05 18:10

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

 


线程同步机制:

      

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


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

 

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

 

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


 

举例:

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(); }}

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


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



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


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

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

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

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

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


总结:

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

9 0
原创粉丝点击