从零开始学多线程之共享对象(二)

 想要使用多线程编程,有一个很重要的前提,那就是必须保证操纵的是线程安全的类.

那么如何构建线程安全的类呢? 1. 使用同步来避免多个线程在同一时间访问同一数据. 2. 正确的共享和安全的发布对象,使多个线程能够安全的访问它们.

那么如何正确的共享和安全的发布对象呢? 这正是这篇博客要告诉你的.

 

1. 多线程之间的可见性问题.

为什么在多线程条件下需要正确的共享和安全的发布对象呢?

这要说到可见性的问题:

 在多线程环境下,不能保证一个线程修改完共享对象的数据,对另一个线程是可见的.

 

一个线程读到的数据也许是一个过期数据,这会导致严重且混乱的问题,比如意外的异常,脏的数据结构,错误的计算和无限的循环.

举个例子:

 

复制代码
public class NoVisibility {     private static int num;     private static boolean ready;      private static class RenderThread extends Thread{         @Override         public void run(){             while(!ready){                 Thread.yield();             }             System.out.println("num = " + num);         }      }          public static void main(String [] args) throws InterruptedException {             new RenderThread().start();             num = 42;             ready = true;      }   }
复制代码

 

 

new RenderThread().start()表示创建一个新线程,并执行线程内的run()方法 ,如果ready的值是false,执行Thread.yield()方法(当前线程休息一会让其他线程执行),这时候再交给main方法的主线程执行,给num赋值42,ready赋值true,然后在任务线程中输出num的值.因为可见性的问题,任务线程可能没有看到主线程对num赋值,而输出0. 

 

我们接下来来看看发布对象也会引发的可见性问题.

 

2. 什么是发布一个对象

 

发布: 让对象内被当前范围之外的代码所使用.

 

复制代码
public class Publish {     public int num1;      private int num2;      public int getNum2(){         return this.num2;     } }
复制代码

 

无论是 publish.num1 还是  publish.getNum2()哪种方法,只要能在类以外的地方获取到对象,我们就称对象被发布了.

如果一个对象在没有完成构造的情况下就发布了,这种情况叫逸出.逸出会导致其他线程看到过期值,危害线程安全.

 

关键字:
50000+
5万行代码练就真实本领
17年
创办于2008年老牌培训机构
1000+
合作企业
98%
就业率

联系我们

电话咨询

0532-85025005

扫码添加微信