学习笔记(2.1)线程、Synchronized、CAS机制、TLAB机制

在JAVA中为了实现事务,通常会使用一些机制保证操作的原子性等问题。

在一段多线程的代码中,在并发情况下,通常会出现因为非线程安全而导致的各种问题。如在以下代码中:

public static int count=0;
	//创建两个线程,在每个线程当中让count自增100次
	public static void main(String[] args){
		for(int i=0;i<2;i++){
			new Thread(
					new Runnable(){
						public void run(){
							try{
								Thread.sleep(10);
							}catch(InterruptedException e){
								e.printStackTrace();
							}
							for(int j=0;j<100;j++){
								count++;
							}
						}
					}
					).start();
		}
		
		try{
			Thread.sleep(1000);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
		System.out.println("count="+count);
	}

由于线程不安全,所以这段代码最终的运行结果中count很有可能会小于200。

而要想使这段代码的最终结果等于200,则可以使用Synchronized同步锁。

public static int count=0;
	//创建两个线程,在每个线程当中让count自增100次
	public static void main(String[] args){
		for(int i=0;i<2;i++){
			new Thread(
					new Runnable(){
						public void run(){
							try{
								Thread.sleep(10);
							}catch(InterruptedException e){
								e.printStackTrace();
							}
							for(int j=0;j<100;j++){
								synchronized(CountTest.class){
									count++;
								}
							}
						}
					}
					).start();
		}
		
		try{
			Thread.sleep(1000);
		}catch(InterruptedException e){
			e.printStackTrace();
		}
		System.out.println("count="+count);
	}

在使用Synchronized同步锁后,count的自增操作具备了原子性,最终结果为200。但是在保证了线程安全的同时,Synchronized也对整个程序的性能问题产生了影响,Synchronized关键字会对其修饰的线程加上一个“锁”,让没有得到“锁”的线程进入等待状态,而争夺到了“锁”,则转变为运行状态,在这一整个操作中,涉及到操作系统用户模式和内核模式的转换,和“锁”资源的来回周转,对于性能的损耗较大代价较高。而在这种时候,我们往往还会采用另一种机制:CAS机制。

CAS机制是英文单词Compare And Swap的缩写,翻译过来就是比较并替换。在CAS机制中,使用了三个基本操作数:内存地址V,旧的预期值A,要修改的新值B。在更新一个变量的时候,只有当变量的预期值A和内存地址V当中的实际值相同时,才会将内存地址V对应的值修改为B。

         即:若在内存地址V中,存储着值为1的变量。此时线程1想要把变量的值增加1,对于线程1来说,A为1,B为2。

                   此时,在线程1要提交更新之前,线程2抢先将V中的变量值改为2,线程1在提交更新时,发现A与V的实际值并不相等,则此次提交失败。

                   线程1重新开始获取当前地址V的值,重新计算后,对于线程1来说A为11,B为12,这个重新尝试的过程称为自旋。

                   此时线程1对此次数据更新进行提交,在对A与V的实际值确认无误后,数据修改成功。

         CAS机制在提升低并发情况下性能的同时,也具有一些无可避免的缺陷:

                   1.CPU开销较大:在高并发的情况下,如果许多线程反复尝试更新某一个变量,却一直没有成功,则会出现反复失败的情况,增大CPU的压力。

                   2.不能保证代码块的原子性:CAS机制所保证的只是一个变量的原子性操作,而不能保证整个代码块的原子性。

                   3.乐观锁普遍出现的ABA问题:A将对变量值进行修改,在此之前B修改了变量的值,在A提交之前,B又将变量的值改回

         在并发度非常高时,使用Synchronized同步锁较为合适,而在并发度较低时,使用CAS更能提高程序的性能。

与CAS机制相同作用的另一种方案,是把内存分配的动作按照线程划分在不同的空间之中进行,即每个线程在JAVA堆中预先分配一小块内存,称为本地线程分配缓冲,哪个线程需要分配内存,就在哪个线程的TLAB上分配,只有TLAB用完并分配新的TLAB时,才需要同步锁定。



  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值