synchronized可见性,synchronized保证三大特性

http://www.itjxue.com  2023-01-06 18:12  来源:未知  点击次数: 

关于JAVA里的加锁synchronized

1.凡使用synchronized标记的方法,比如 public synchronized void func1() { .... },则同时只有一个线程能够运行这个方法。比如,线程1正在运行func1,则其他线程需要运行func1的话,会卡住,等线程1运行func1结束后,其他线程中,才会有一个幸运儿成功争取到运行func1的资格,然后这个幸运儿线程开始运行func1。没有争取到运行资格的其他线程,会继续等待。

2.你的例子中,被锁定的是 方法 m1,而不是属性b。所以,m1的synchronized加锁操作,与b没有半点毛钱关系。

3.要实现你的锁b想法,其实很简单。去买一件贞操宝甲来就行了。开玩笑,哈哈。要锁b,把main方法里的tt.m2()修改为tt.m1()。

4.以后别用“b”作为变量,总觉得怪怪了。也许你现在还没长大,很单纯。但大人的世界里,“b”是一种不文雅但又对人类的未来有重要作用的东西。建议用cb来代替b。

synchronized能保证可见性吗

volatile和synchronized的区别:

1.volatile本质是在告诉jvm当前变量在寄存器(工作内存)中的值是不确定的,需要从主存中读取;synchronized则是锁定当前变量,只有当前线程可以访问该变量,其他线程被阻塞住。

2.volatile仅能使用在变量级别;synchronized则可以使用在变量、方法、和类级别的。

3.volatile仅能实现变量的修改可见性,并能保证原子性;而synchronized则可以保证变量的修改可见性和原子性。

4.volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。

5.volatile标记的变量不会被编译器优化;synchronized标记的变量可以被编译器优化。

每日一问:谈谈 synchronized 和 CAS 机制

昨天的文章 我们针对 Java 语言的 "happends-before" 原则做了一个非常简单的表述,以致于有同学提到我这个话语的严谨性问题。而这个原则在 Java 语言里面非常重要,以致于我必须重新引用一下相关书籍的话来进行论述。

"happends-before" 先行发生原则是 Java 内存模型中定义的两项操作之间的偏序关系,如果说操作 A 先行发生于操作 B,那么操作 A 产生的影响一定应该被操作 B 所观察到。

而对于我们 volatile 保证的可见性, synchronized 和 final 关键字也同样可以做到。那我们今天就来简单讲一下我们非常常用的 synchronized 和似乎在 Android 中少有听到的 CAS 机制。

synchronized 采用的是 CPU 悲观锁机制,即线程获得的是独占锁。独占锁就意味着 其他线程只能依靠阻塞来等待线程释放锁 。而在 CPU 转换线程阻塞时会引起线程上下文切换,当有很多线程竞争锁的时候,会引起 CPU 频繁的上下文切换导致效率很低。尽管 Java1.6 为 synchronized 做了优化,增加了从偏向锁到轻量级锁再到重量级锁的过度,但是在最终转变为重量级锁之后,性能仍然较低。

CAS 是英文单词 Compare And Swap 的缩写,翻译过来就是比较并替换。它当中使用了3个基本操作数:内存地址 V,旧的预期值 A,要修改的新值 B。采用的是一种乐观锁的机制,它不会阻塞任何线程,所以在效率上,它会比 synchronized 要高。所谓乐观锁就是: 每次不加锁而是假设没有冲突而去完成某项操作,如果因为冲突失败就重试,直到成功为止。

所以,在并发量非常高的情况下,我们尽量的用同步锁,而在其他情况下,我们可以灵活的采用 CAS 机制。

在 java.util.concurrent.atomic 包下,一系列以 Atomic 开头的包装类。例如 AtomicBoolean , AtomicInteger , AtomicLong 等,它们就是典型的利用 CAS 机制实现的原子操作类。

此外, Lock 系列类的底层实现以及 Java 1.6 在 synchronized 转换为重量级锁之前,也会采用到 CAS 机制。

关于 CAS 机制的更多相关信息请移步:

漫画:什么是CAS机制?(进阶篇)

synchronized和volatile区别

1、关键字不同

volatile?关键字是线程同步的轻量级实现,所以?volatile?性能肯定比synchronized关键字要好?。但是?volatile?关键字只能用于变量而?synchronized?关键字可以修饰方法以及代码块?。

2、修饰功能不同

volatile只能修饰变量,synchronized可以修饰方法、代码块。

3、线程阻塞情况不同

volatile不会造成线程的阻塞;synchronized可能会造成线程的阻塞。

4、原子性不同

volatile保证数据的可见性,但不能保证原子性;而synchronized可以保证原子性,也可以间接保证可见性,因为它会将私有内存中和公共内存中的数据做同步。

谈谈synchronized与ReentrantLock的区别

【死记硬背】

synchronized是JVM层面的锁,是Java关键字,通过monitor对象来完成(monitorenter与monitorexit),对象只有在同步块或同步方法中才能调用wait/notify方法。

ReentrantLock是从jdk1.5以来(java.util.concurrent.locks.Lock)提供的API层面的锁。

1 都是用来协调多线程对共享对象、变量的访问;

2 都是可重入锁,同一线程可以多次获得同一个锁;

3 都保证了可见性和互斥性;

1 ReentrantLock显示的获得、释放锁,synchronized隐式获得释放锁;

2 ReentrantLock可响应中断、可轮回,synchronized是不可以响应中断的,为处理锁的不可用性提供了更高的灵活性;

3 ReentrantLock是API级别的,synchronized是JVM级别的;

4 ReentrantLock可以实现公平锁,而synchronized不行;

5 ReentrantLock通过Condition可以绑定多个条件;

6 底层实现不一样,synchronized是同步阻塞,使用的是悲观并发策略,Lock是同步非阻塞,采用的是乐观并发策略;

7 Lock 是一个接口,而 synchronized 是 Java 中的关键字,synchronized 是内置的语言

实现。

8 synchronized 在发生异常时,会自动释放线程占有的锁,因此不会导致死锁现象发生;而Lock在发生异常时,如果没有主动通过unLock()去释放锁,则很可能造成死锁现象,因此使用 Lock 时需要在 finally 块中释放锁。

9 Lock可以让等待锁的线程响应中断,而 synchronized却不行,使用synchronized时,等待的线程会一直等待下去,不能够响应中断;

10 通过Lock可以知道有没有成功获取锁,而synchronized却无法办到;

11 Lock 可以提高多个线程进行读操作的效率,既就是实现读写锁等;

【答案解析】

synchronized的锁使用案例:

ReentrantLock的锁使用案例:

【温馨提示】

(责任编辑:IT教学网)

更多

相关ASP教程文章

推荐ASP教程文章