多线程2
来源:互联网 发布:c语言绝对值函数fabs 编辑:程序博客网 时间:2024/05/02 04:58
/**
* volatile 关键字,使一个变量在多个线程间可见
* A B线程都用到一个变量,java默认是A线程中保留一份copy,这样如果B线程修改了该变量,则A线程未必知道
* 使用volatile关键字,会让所有线程都会读到变量的修改值
*
* 在下面的代码中,running是存在于堆内存的t对象中
* 当线程t1开始运行的时候,会把running值从内存中读到t1线程的工作区,在运行过程中直接使用这个copy,并不会每次都去
* 读取堆内存,这样,当主线程修改running的值之后,t1线程感知不到,所以不会停止运行
*
* 使用volatile,将会强制所有线程都去堆内存中读取running的值
*
* 可以阅读这篇文章进行更深入的理解
* http://www.cnblogs.com/nexiyi/p/java_memory_model_and_thread.html
*
* volatile并不能保证多个线程共同修改running变量时所带来的不一致问题,也就是说volatile不能替代synchronized
* @author mashibing
*/
public class T { /*volatile*/ boolean running = true; //对比一下有无volatile的情况下,整个程序运行结果的区别 void m() { System.out.println("m start"); while(running) { /* try { TimeUnit.MILLISECONDS.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); }*/ } System.out.println("m end!"); } public static void main(String[] args) { T t = new T(); new Thread(t::m, "t1").start(); try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } t.running = false; }}
/**
* volatile并不能保证多个线程共同修改running变量时所带来的不一致问题,也就是说volatile不能替代synchronized
* 运行下面的程序,并分析结果(不保证写的一致性,只保证读一致性,不保证原子性)
* @author mashibing
*/
public class T { volatile int count = 0; void m() { for(int i=0; i<10000; i++) count++; } public static void main(String[] args) { T t = new T(); List<Thread> threads = new ArrayList<Thread>(); for(int i=0; i<10; i++) { threads.add(new Thread(t::m, "thread-"+i)); } threads.forEach((o)->o.start()); threads.forEach((o)->{ try { o.join(); } catch (InterruptedException e) { e.printStackTrace(); } }); System.out.println(t.count); }}
/**
* 对比上一个程序,可以用synchronized解决,synchronized可以保证可见性和原子性,volatile只能保证可见性
* @author mashibing
*/
/**
* 解决同样的问题的更高效的方法,使用AtomXXX类
* AtomXXX类本身方法都是原子性的,但不能保证多个方法连续调用是原子性的
* @author mashibing
*/
public class T { /*volatile*/ //int count = 0; //Atomic** 多个方法之间依然不能保证是原子性的,仅仅一个方法适合 AtomicInteger count = new AtomicInteger(0); /*synchronized*/ void m() { for (int i = 0; i < 10000; i++) //if count.get() < 1000 count.incrementAndGet(); //count++ } public static void main(String[] args) { T t = new T(); List<Thread> threads = new ArrayList<Thread>(); for (int i = 0; i < 10; i++) { threads.add(new Thread(t::m, "thread-" + i)); } threads.forEach((o) -> o.start()); threads.forEach((o) -> { try { o.join(); } catch (InterruptedException e) { e.printStackTrace(); } }); System.out.println(t.count); }}
/**
* synchronized优化
* 同步代码块中的语句越少越好
* 比较m1和m2
* @author mashibing
*/
public class T { int count = 0; synchronized void m1() { //do sth need not sync try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } //业务逻辑中只有下面这句需要sync,这时不应该给整个方法上锁 count ++; //do sth need not sync try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } void m2() { //do sth need not sync try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } //业务逻辑中只有下面这句需要sync,这时不应该给整个方法上锁 //采用细粒度的锁,可以使线程争用时间变短,从而提高效率 synchronized(this) { count ++; } //do sth need not sync try { TimeUnit.SECONDS.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } }}
/**
* 锁定某对象o,如果o的属性发生改变,不影响锁的使用
* 但是如果o变成另外一个对象,则锁定的对象发生改变
* 应该避免将锁定对象的引用变成另外的对象
* @author mashibing
*/
public class T { Object o = new Object(); void m() { synchronized(o) { while(true) { try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()); } } } public static void main(String[] args) { T t = new T(); //启动第一个线程 new Thread(t::m, "t1").start(); try { TimeUnit.SECONDS.sleep(3); } catch (InterruptedException e) { e.printStackTrace(); } //创建第二个线程 Thread t2 = new Thread(t::m, "t2"); t.o = new Object(); //锁对象发生改变,所以t2线程得以执行,如果注释掉这句话,线程2将永远得不到执行机会 t2.start(); }}
/**
* 不要以字符串常量作为锁定对象
* 在下面的例子中,m1和m2其实锁定的是同一个对象
* 这种情况还会发生比较诡异的现象,比如你用到了一个类库,在该类库中代码锁定了字符串“Hello”,
* 但是你读不到源码,所以你在自己的代码中也锁定了”Hello”,这时候就有可能发生非常诡异的死锁阻塞,
* 因为你的程序和你用到的类库不经意间使用了同一把锁
*
* jetty
*
* @author mashibing
*/
public class T { String s1 = "Hello"; String s2 = "Hello"; void m1() { synchronized(s1) { } } void m2() { synchronized(s2) { } }}
- 多线程2
- 多线程2
- 多线程 - 2
- 多线程2
- 多线程2
- 多线程2
- 多线程-2
- 多线程2
- 多线程2
- 多线程2
- 多线程2
- 多线程2
- 多线程2
- 多线程-2
- 多线程2
- 多线程2
- 多线程(2):
- 多线程2
- 酷狗8.0升级蝰蛇音效,让你的耳朵跟着音乐走
- DOBBY口袋无人机淘宝众筹首日破500万,自拍无人机受热捧
- 难道微博被盗?这家手机厂商居然说“放下手机”
- [LeetCode] 538.Convert BST to Greater Tree
- Codeforces Round #428 (Div. 2) D
- 多线程2
- python——深浅copy 及一些补充知识点
- linux学习---信号(signal,sigaction,kill,sigqueue,sigprocmask,sigpending,sigsuspend)
- Snapchat收购了一家3D成像公司,但似乎被坑了
- 第一行代码读书笔记-第十二章 Material Design实战
- 百万韩粉集中进入某直播平台原因何在?
- 创业路上无数坑,商标问题最不容小觑!
- 网红经济对接综艺节目 湖南卫视这步棋走得妙
- 除了发布Ticwatch 2,出门问问还“跨界‘带来另一款产品