您现在的位置是:首页 > 文章详情

java并发(二):深入分析volatile实现原理

日期:2018-10-28点击:356

volatile的原理实现可以看这篇文章,真的是从硬件层面上说明了volatile怎样保证可见性

img_47c75ff4a413a7ad2040f5796bbf0501.png

下面这个实例,如果没有设置成volatile关键字,那么线程读的 isRunning永远都是自己私有内存中的,线程将会一直在while循环中

public class RunThread extends Thread{ private volatile boolean isRunning = true; private void setRunning(boolean isRunning){ this.isRunning = isRunning; } public void run(){ System.out.println("进入run方法.."); int i = 0; while(isRunning == true){ //.. } System.out.println("线程停止"); } public static void main(String[] args) throws InterruptedException { RunThread rt = new RunThread(); rt.start(); Thread.sleep(1000); rt.setRunning(false); System.out.println("isRunning的值已经被设置了false"); } } 
img_3f6e7215fab75d8e4e066ad4e412d485.png
img_0c30a913ffe2754fb3ea1e2e7c7212cd.png

这是展示volatile虽然有可见性,但是没有原子性:

 /** * volatile关键字不具备synchronized关键字的原子性(同步) * @author alienware * */ public class VolatileNoAtomic extends Thread{ private static volatile int count = 0; //这个被注释的代码可以保证结果正确 //private static AtomicInteger count = new AtomicInteger(0); private static void addCount(){ for (int i = 0; i < 1000; i++) { count++ ; //这个被注释的代码可以保证结果正确 //count.incrementAndGet(); } System.out.println(count); } public void run(){ addCount(); } public static void main(String[] args) { VolatileNoAtomic[] arr = new VolatileNoAtomic[100]; for (int i = 0; i < 10; i++) { arr[i] = new VolatileNoAtomic(); } for (int i = 0; i < 10; i++) { arr[i].start(); } } } 

这是使用atomic,保证原子性的代码:

public class AtomicUse { private static AtomicInteger count = new AtomicInteger(0); //多个addAndGet在一个方法内是非原子性的,需要加synchronized进行修饰,保证4个addAndGet整体原子性 /**synchronized*/ public synchronized int multiAdd(){ try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } count.addAndGet(1); count.addAndGet(2); count.addAndGet(3); count.addAndGet(4); //+10 return count.get(); } public static void main(String[] args) { final AtomicUse au = new AtomicUse(); List<Thread> ts = new ArrayList<Thread>(); for (int i = 0; i < 100; i++) { ts.add(new Thread(new Runnable() { @Override public void run() { System.out.println(au.multiAdd()); } })); } for(Thread t : ts){ t.start(); } } } 

线程通信

img_9b28cecb9ab991391e3dcf82e21301d7.png

ListAdd2.java,可以看出本来list已经到5了,那么t2应该出while循环抛异常,但是因为它执行了wait方法,释放锁了。而t1得到锁一直执行,虽然t1执行了notify方法,但是只是发出通知而已,只有它的方法执行完才释放锁让t2执行。

package com.bjsxt.base.conn008; import java.util.ArrayList; import java.util.List; import java.util.Queue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.LinkedBlockingDeque; import java.util.concurrent.LinkedBlockingQueue; /** * wait notfiy 方法,wait释放锁,notfiy不释放锁 * @author alienware * */ public class ListAdd2 { private volatile static List list = new ArrayList(); public void add(){ list.add("bjsxt"); } public int size(){ return list.size(); } public static void main(String[] args) { final ListAdd2 list2 = new ListAdd2(); // 1 实例化出来一个 lock // 当使用wait 和 notify 的时候 , 一定要配合着synchronized关键字去使用 final Object lock = new Object(); // final CountDownLatch countDownLatch = new CountDownLatch(1); Thread t1 = new Thread(new Runnable() { @Override public void run() { try { synchronized (lock) { for(int i = 0; i <10; i++){ list2.add(); System.out.println("当前线程:" + Thread.currentThread().getName() + "添加了一个元素.."); Thread.sleep(500); if(list2.size() == 5){ System.out.println("已经发出通知.."); // countDownLatch.countDown(); lock.notify(); } } } } catch (InterruptedException e) { e.printStackTrace(); } } }, "t1"); Thread t2 = new Thread(new Runnable() { @Override public void run() { synchronized (lock) { if(list2.size() != 5){ try { System.out.println("t2进入..."); lock.wait(); // countDownLatch.await(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println("当前线程:" + Thread.currentThread().getName() + "收到通知线程停止.."); throw new RuntimeException(); } } }, "t2"); t2.start(); t1.start(); } } 
img_83a2b5a96b930a497cc8c0f863d9781f.png
package com.xushu.multi; import java.util.LinkedList; import java.util.concurrent.TimeUnit; import java.util.concurrent.atomic.AtomicInteger; public class MyQueue { private LinkedList<Object> list = new LinkedList<Object>(); private AtomicInteger count = new AtomicInteger(0); private final int minSize = 0; private final int maxSize; public MyQueue(int size) { this.maxSize = size; } private final Object lock = new Object(); public void put(Object obj) { synchronized (lock) { if (count.get() == this.maxSize) { try { lock.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } list.add(obj); count.incrementAndGet(); lock.notify(); System.out.println("新加入的元素为:" + obj); } } public Object take() { Object ret = null; synchronized (lock) { if (count.get() == minSize) { try { lock.wait(); } catch (InterruptedException e) { // TODO Auto-generated catch block e.printStackTrace(); } } ret = list.removeFirst(); count.decrementAndGet(); lock.notify(); } return ret; } public int getSize() { return this.count.get(); } public static void main(String[] args) { final MyQueue mq = new MyQueue(5); mq.put("a"); mq.put("b"); mq.put("c"); mq.put("d"); System.out.println("当前容器的长度:" + mq.getSize()); Thread t1 = new Thread(new Runnable() { @Override public void run() { mq.put("f"); mq.put("g"); mq.put("e"); } }, "t1"); t1.start(); Thread t2 = new Thread(new Runnable() { @Override public void run() { Object o1 = mq.take(); System.out.println("移除的元素为:" + o1); Object o2 = mq.take(); System.out.println("移除的元素为:" + o2); } }, "t2"); try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } t2.start(); } } 
原文链接:https://yq.aliyun.com/articles/669583
关注公众号

低调大师中文资讯倾力打造互联网数据资讯、行业资源、电子商务、移动互联网、网络营销平台。

持续更新报道IT业界、互联网、市场资讯、驱动更新,是最及时权威的产业资讯及硬件资讯报道平台。

转载内容版权归作者及来源网站所有,本站原创内容转载请注明来源。

文章评论

共有0条评论来说两句吧...

文章二维码

扫描即可查看该文章

点击排行

推荐阅读

最新文章