Java多线程(三)synchronized volatile 以及 原子性 有序性和可见性 7.25

三大性质

原子性

原子性是指一个操作是不可中断要么全部执行成功要么全部执行失败

由原子性变量操作read,load,use,assign,store,write,

可以大致认为基本数据类型的访问读写具备原子性(例外就是long和double的非原子性协定)

synchronized满足原子性;

volatile并不能保证原子性

如果让volatile保证原子性,必须符合以下两条规则:

1)运算结果并不依赖于变量的当前值,或者能够确保只有一个线程修改变量的值;

2)变量不需要与其他的状态变量共同参与不变约束

有序性

synchronized具有有序性

volatile包含禁止指令重排序的语义,其具有有序性;

java程序天然的有序性可以总结为:如果在本线程内观察,所有的操作都是有序的;如果在一个线程观察另一个线程,所有的操作都是无序的

可见性

可见性是指当一个线程修改了共享变量后,其他线程能够立即得知这个修改。通过之前对synchronized内存语义进行了分析,当线程获取锁时会从主内存中获取共享变量的最新值,释放锁的时候会将共享变量同步到主内存中。从而,synchronized具有可见性。同样的在volatile分析中,会通过在指令中添加lock指令,以实现内存可见性。因此, volatile具有可见性

相关链接:https://www.jianshu.com/p/cf57726e77f2

public class ThreadV extends Thread{
	volatile public static int count;
	synchronized private static void addCount() {
		for (int i = 0; i < 100; i++) {
			count++;
		}
		System.out.println("count = " + count);
	}
	public void run() {
		addCount();
	}
}
public class RunV {
	public static void main(String[] args) {
		ThreadV[] tarr = new ThreadV[100];
		for(int i = 0; i < 100; i++) {
			tarr[i] = new ThreadV();
 		}
		for(int i = 0; i < 100; i++) {
			tarr[i].start();
		}
	}
}


使用原子类进行i++操作:


import java.util.concurrent.atomic.AtomicInteger;

public class AddCountThread extends Thread{
	private AtomicInteger count = new AtomicInteger(0);
	public void run() {
		for (int i = 0; i < 10000; i++) {
			System.out.println(count.incrementAndGet());
		}
	}
}
public class RunAddCount {
	public static void main(String[] args) {
		AddCountThread countService = new AddCountThread();
		Thread t1 = new Thread(countService);
		t1.start();
		Thread t2 = new Thread(countService);
		t2.start();
		Thread t3 = new Thread(countService);
		t3.start();
		Thread t4 = new Thread(countService);
		t4.start();
		Thread t5 = new Thread(countService);
		t5.start();
	}
}

原子类也并不完全安全

import java.util.concurrent.atomic.AtomicLong;

public class Service {
	public static AtomicLong aiRef = new AtomicLong();
	synchronized public void addNum() {
		System.out.println(Thread.currentThread().getName()
							+ "加了100之后的值是:" + aiRef.addAndGet(100));
		aiRef.addAndGet(1);
	}
}
public class ThreadS extends Thread{
	private Service service;
	public ThreadS(Service service) {
		super();
		this.service = service;
	}
	public void run() {
		service.addNum();
	}
}
public class RunS {
	public static void main(String[] args) {
		try {
			Service service = new Service();
			ThreadS[] array = new ThreadS[5];
			for (int i = 0; i < array.length; i++) {
				array[i] = new ThreadS(service);
			}
			for (int i = 0; i < array.length; i++) {
				array[i].start();
			}
			Thread.sleep(1000);
			System.out.println(service.aiRef.get());
		} catch (InterruptedException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

synchronized代码块具有volatile同步的功能

总之:synchronized: 具有原子性,有序性和可见性
           volatile:具有有序性和可见性

 

关键字synchronized可以保证在同一时刻,只有一个线程可以执行某一个方法或者某一个代码块。它包含两个特征:互斥性和可见性。同步synchronized不仅可以解决一个线程看到对象处于不一致的状态,还可以保证进入同步方法或者同步代码块的每个线程,都看到由同一个锁保护之前所有的修改效果。

学习完多线程同步之后就可以有效控制线程间处理数据的顺序性,及对处理后的数据进行有效值的保证,更好地对线程执行结果有正确的预期。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值