您的位置:首页 > 编程语言 > Java开发

Java多线程(2)-基础介绍

2017-01-14 21:27 309 查看
基础介绍



一.线程安全性



(1)概念

1.共享: 变量在多个线程中访问。

2.可变: 变量在其生命周期内可发生变化。

3.一个对象是否是线程安全的,取决于它是否被多个线程访问,同时满足于“共享”和“可变”这两个条件的变量,必须要添加同步机制以保证变量的线程安全性,而不同时满足的这两个条件的变量则是线程安全的。

4.原子性: 一个变量或一个复合过程在一个线程使用时,其他线程无法访问或者修改这个变量或者过程。

5.可见性: 一个变量在某一个线程中修改后,其他线程马上就能知道此变量已被修改。

   正确的加锁既能保证锁中代码段的原子性,同时也能保证代码中对象的可见性。

6.为什么会有线程安全问题存在

例如 两个线程共同调用i++ , 会发生如下事件



可以看出i++并不是一个原子操作,它伴随这是个 读取->修改->写入 的操作序列,而线程二读取的时候,有可能线程一正在修改其值。这样就造成了顺序的混乱。产生线程安全性问题。

(7)重排序

private static boolean ready = false;
private static int number = 0;
private static class ReaderThread extends Thread{
@Override public void run() {
while(!ready) Thread.yield();
System.out.println(number);
}
}

public static void main(String[] arge){
new ReaderThread().start();
number = 42;
ready = true;
}

因为可见性的原因主线程修改了ready的值,可能永远无法被Reader线程看到,所以循环可能一直进行下去。还有一种情况,输出number有可能为0,大家可能感到奇怪为什么已经给number赋值为42了,而显示会为0。这是因为在没有同步措施的情况下编译器和处理器以及运行时,都可能对程序的执行顺序进行意想不到的调整,并不像程序中所描述一样。这种现象叫做重排序。但是只要进行正确的同步这种情况就能被避免。

(2)以下几种情况可视为线程安全情况

1.不在线程之间共享该变量。

2.变量状态为final修饰的不可变的变量。

3.在线程间正确使用同步机制的变量。

4.方法中或者线程中包含的局部变量(变量不可被发布出去)。

(3)最低安全性保障

在没有同步措施的情况下,可能会读取一个失效值,但至少这个值是之前某个线程设置的。但是非volatile类型的long和double变量,JVM运行将64位的读写操作分解成两个32位的操作。如果没有同步保证,那么很可能会读取到某个线程设置的高32位,和另一个线程设置的低32位,这样连最低安全性都无法保障,所以不要抱有侥幸心理,赶紧用锁保护起来吧。

(4)Volatile变量描述

volatile变量不会造成线程阻塞,所以volatile是比synchronized更轻量级的一种同步机制。把一个变量声明为volatile后编译器以及运行时都会注意到这个变量是共享的。因此不会对这个变量操作进行重排序。其他线程对这个变量进行修改时会直接在主内存(其他线程可见)上修改,不会把它缓存到自己线程内存中。所以读取volatile类型的变量时都会读取到最新的修改值。可以说volatile能够保证变量的可见性。(典型应用:判断线程中循环退出)

注意:volatile无法保证原子性(因为它无法提供 读->写->改 的原子操作)它只能保证改后可见。

(5)设计同步类遵循的一些规则,帮助更好的设计程序

1.在设计多线程访问类时,设计线程安全的变量可以优先考虑前两种情况,能提高程序效率。加锁是最后考虑的。

2.需要同步的变量越少,越容易实现正确的同步,同时也能更加容易判断此变量在多线程中使用的情况,从而更好的优化设计类。

3.更好的封装,将多线程的复杂性都封装在类的内部,遵循依赖倒置原则。这样能更好的实现线程的安全性。后期的代码维护会相对容易。

4.对于已经正确运行且符合性能要求的多线程程序,要谨慎修改,因为并发错误往往是难以重现和调试的。

5.即使全部采用线程安全类来构建程序,依然无法保证程序是线程安全的。因为每个线程安全类只保证类内部线程安全。而外部调用的原子性依然无法保证。

6.为了保证活跃性和性能,尽量减少同步方法的使用,细化同步锁,不需要同步的代码尽量抽离同步块,不要将耗时操作放入同步块中。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: