Java并发编程——第3章:对象的共享(一)

本章将介绍如何共享和发布对象,从而使他们能够安全地由多个线程访问。

3.1 可见性

当读操作和写操作在不同的线程中执行时,我们无法确保执行读操作的线程能适时的看到其他线程写入的值,有时甚至是根本不可能的事。为了确保多个线程之间对写操作的可见性,必须引入同步机制。

实例代码 (┬_┬):

package chapter3;
//因为代码中没有引入同步机制,所以无法保证主程序写入的ready和number被读线程读入
public class NoVisibility {

	public static boolean ready;
	public static int number;
	
	public static class readThread extends Thread{
		public void run(){
			while(!ready){
				Thread.yield();
			}
			System.out.println(number);
		}
	}
	
	public static void main(String[] args) {
		new readThread().run();
		ready = true;
		number = 42;
	}

}

因为代码中没有引入同步机制,所以无法保证主程序写入的ready和number被读线程读入。

 解决办法:只要有数据在多个线程间共享,就使用正确的同步。

3.1.1 失效数据

   这段代码是非线程安全的,因为set和get都是在没有同步的情况下访问value的。与其他问题相比,失效值问题更容易出现:

如果某个线程调用了set,另一个调用get函数的线程可能能看到更新后的value,也可能看不到。

3.1.2 非原子的64位操作

      但保证至少这个值是之前某个线程设置的值,而不是一个随机值,这种安全性保证也称最低安全性。其适用于绝大多数变量,但是非volatile64位数值变量(double和long)是例外。JVM要求变量的读取和写入操作都必须是原子操作。但是对于非volatile64位变量来说,其分为两部分32位分别读取。所以很可能出现读取某个值的高32位和另外一个值的低32位。除非用volatile声明他们或者用锁保护他们。

3.1.3 加锁与可见性

 

加锁的含义不止是互斥行为,还包括内存可见性

为了确保所有线程都能看到共享变量的最新值,所有执行读操作或者写操作的线程都必须在同一个锁上同步。

猜你喜欢

转载自blog.csdn.net/Curry7895/article/details/82687743
今日推荐