synchronized和ReentrantLock有什么区别?有人说synchronized最
典型回答 synchronized是java内建的同步机制,所以有人称其为instrinisc Locking(固有锁),它提供了互斥的语义和可见性,当一个线程已经获取当前锁时,其他试图获取的线程只能等待或者阻塞在那里。 在java5以前,synchronized是仅有的同步手段,在代码中,synchronized可以用来修饰方法,也可以使用在特定的代码块上,本质上sychronized方法等同于把方法全部语句synchronized块包起来。 ReentrantLock,通常翻译为再入锁,是java5提供的锁实现,它的语义和synchronized基本相同。再入锁通过代码直接调用lock()方法获取,代码书写更加灵活。与此同时ReentrantLock提供了很多实 用的方法,能够提供很多synchronized无法做到的细节控制,比如可以控制fairness,也就是公平性,或者利用定义条件等。但是,编码中也需要注意,必须明确调用unlock()方法释放,不然就会一直持有该锁。 synchronized和ReentrantLock的性能不能一概而论,早期版本synchronized在很多场景下性能相差较大,在后续版本进行了较多改进,在低竞争场景中表现可能优于ReentrantLock. 接下为理解锁来扩展下知识 首先,理解什么是线程安全 定义:线程安全是一个多线程环境下正确性的概念,也就是保证多线程环境下共享的,可以修改的状态的正确性,这里的状态反映在程序中其实可以看做是数据。 换个角度来看,如果状态不是共享的,或者不是可修改的,也就不存在线程安全问题,进而知道保证线程安全的两个办法:
线程安全需要保证几个基本特性:
稍微有点难懂,看下代码,分析下原子性需求体现在哪里。这个例子通过取两次数值然后进行对比,来模拟两次对共享状态的操作。 你可以编译并执行,可以看到,仅仅是两个线程的低度并发,就非常容易碰到former和latter不相等的情况。这是因为,在两次取值的过程中,其他线程可能已经修改了shareState。 public class ThreadSafeSample { public int shareState; public void nonSafeAction(){ while(shareState<100000){ int former = shareState++; int latter = shareState; if(former !=latter - 1){ System.out.println("Observed data race,former is"+former+","+"latter is"+latter); } } } public static void main(String[] args) throws InterruptedException{ final ThreadSafeSample sample = new ThreadSafeSample(); Thread threadA = new Thread(){ public void run(){ sample.nonSafeAction(); } }; Thread threadB = new Thread(){ public void run(){ sample.nonSafeAction(); } }; threadA.start(); threadB.start(); threadA.join(); threadB.join(); } } 运行结果 Observed data race,former is62,latter is64 但是如果加上? public class ThreadSafeSample { public int shareState; public void nonSafeAction(){ while(shareState<100000){ synchronized(this){ int former = shareState++; int latter = shareState; if(former !=latter - 1){ System.out.println("Observed data race,"+"latter is"+latter); } } } } public static void main(String[] args) throws InterruptedException{ final ThreadSafeSample sample = new ThreadSafeSample(); Thread threadA = new Thread(){ public void run(){ sample.nonSafeAction(); } }; Thread threadB = new Thread(){ public void run(){ sample.nonSafeAction(); } }; threadA.start(); threadB.start(); threadA.join(); threadB.join(); } } 就不会有显示结果,这样保证了安全性 今天先写到这里 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |