`

线程安全扫盲贴三——共享实例(Sharing Objects)

 
阅读更多

       前面说了如何管理对共享、易变状态的数据的状态的访问,《JAVA并发编程》第三章主要介绍共享和发布可以被多线程安全访问的对象,使用了java.util.concurrent包下的类为基础,创建线程安全的类和构建安全的并发应用程序。

           synchronized不仅仅与操作原子性和关键区域定界相关,它还有个重要却不明显的作用——内存可见性。同步不仅仅是防止线程修改正在被别的线程使用的对象状态,还可以保证当一个线程修改了对象状态后,其他线程可以看到状态的更新。通过显示的同步或利用内置的同步的类库,可以保证发布的对象是线程安全的。

 

可见性

      当一个线程对对象状态进行读操作,另一个线程对该对象状态进行写操作时,如果没有线程同步,则无法保证读对象的线程能即时的读取到写对象更新后的值。

 

package com.zyp.test.concurrent;

public class NoVisibility {
	private static boolean ready;//默认值为false
	private static int number;

	private static class ReaderThread extends Thread {
		public void run() {
			while (!ready)
				Thread.yield();
			System.out.println(number);
		}
	}

	public static void main(String[] args) {
		new ReaderThread().start();
		number = 42;
		ready = true;
		System.out.println("end");
	}
}

这段代码中有两个线程,一个主线程和一个读线程都要反问number和ready。主线程启动读线程后,将ready置为true。读线程一直循环,直到发现ready为true后,打印number的值。看起来读线程打印结果:
1:可能是明显的42,

2:也可能打印出0,

3:也可能永远不停止。

因为没有适当的同步,不能保证主线程写了number和ready一定对读线程是可见的。上面读线程可能永远不停止,因为ready可能对读线程永远不可见。上面可能打印出0,跟重排序有关。

重排序(reordering):在一个线程中的方法的执行顺序并不保证与代码中顺序一致。在没有同步的情况下,java内存模型(JMM)允许编译器重新排序操作,以获取多处理器带来的更多好处。

重排序后,编译器后的代码可能先执行ready的赋值再执行number的赋值。

 

 

 

分享到:
评论
1 楼 fantasy 2013-03-13  
写得不错 加油!

相关推荐

    线程,同步与锁————Lock你到底锁住了谁?.htm

    线程,同步与锁————Lock你到底锁住了谁?.htm

    多线程编程之三——线程间通讯

    当一个程序中存在多个并发执行的线程时,它们可能需要共享数据或者互相通知事件的发生,这就需要线程间通信机制。下面将详细讨论几种常见的线程间通信方式。 1. 使用全局变量进行通信 全局变量是所有线程都能访问的...

    并发编程——认识java里的线程(csdn)————程序.pdf

    并发编程——认识 Java 里面的线程 在 Java 编程中,并发编程是一个非常重要的概念。Java 程序天生就是多线程的,main 方法开始执行后,按照既定的代码逻辑执行,看似没有其他线程参与,但实际上 Java 程序天生就是...

    python进程、线程(csdn)————程序.pdf

    在Python编程中,进程和线程是并发执行任务的基础概念,它们允许程序同时处理多个任务,提高系统的效率和响应速度。下面将详细解释这些概念及其相关的工具和机制。 ### 进程 进程是计算机中运行的程序的一个实例,...

    java初学者适用——java实例大全

    【Java初学者适用——Java实例大全】是一份专为初学者设计的教程资源,它涵盖了大量实际编程案例,旨在帮助新手快速掌握Java编程语言。在Java的世界里,实践是掌握知识的关键,通过实例学习能够更好地理解和应用理论...

    《Visual C++范例大全》随书光盘 第十一章

    第11章 实例257——使用Win32 ... 实例274——三种方法实现启动其他的应用程序 实例275——使用剪贴板实现程序间的数据交换 实例276——通过内存映射实现进程间的数据交换 实例277——通过消息机制实现进程间的通信

    C# 多线程实例多线程实例多线程实例

    对于静态成员、全局变量和共享对象,必须确保它们在多线程环境中的访问是安全的。使用`volatile`关键字、`Interlocked`类或其他同步机制可以帮助实现线程安全。 8. Task并行库(TPL): .NET Framework 4.0引入了...

    数据结构(C语言版)——共享栈

    总结来说,"数据结构(C语言版)——共享栈"是一个关于在C语言中实现线程安全的数据结构的项目。它涵盖了栈的基本操作以及在多线程环境下的同步和通信技术,是理解和实践并发编程的重要实例。通过这样的实践,开发者...

    多线程安全退出实例源代码

    这个实例源代码,"ThreadSafeExit",很可能提供了一种确保线程在完成工作后正确、安全地终止的方法。下面我们将深入探讨多线程安全退出的重要性以及实现策略。 首先,理解为什么需要安全退出。在多线程环境中,线程...

    python实现线程池并可自动拓展和减小线程数(csdn)————程序.pdf

    在Python编程中,线程池是一种管理多个线程并发执行任务的有效工具,它可以有效地调度和控制线程的数量,从而优化系统资源的使用。本篇将介绍如何使用Python实现一个线程池,该线程池还能根据设定的时间自动扩展和...

    设计模式——单实例模式、单件模式——Java编写

    饿汉式是在类加载时就完成了初始化,因此类加载比较慢,但获取实例的速度快,且线程安全。代码如下: ```java public class Singleton { private static final Singleton INSTANCE = new Singleton(); private ...

    Visual C++开发GIS系统——开发实例剖析guangpan

    《Visual C++开发GIS系统——开发实例剖析guangpan》这本书着重讲解了如何利用Microsoft的Visual C++编程环境来开发地理信息系统(GIS)的应用程序。GIS是计算机科学与地理学的交叉领域,它用于采集、存储、管理和...

    Java多线程之定时任务 以及 SpringBoot多线程实现定时任务——异步任务

    1. SpringBoot 自定义线程池以及多线程间的异步调用(@Async、@EnableAsync) 2.Java多线程之定时任务 以及 SpringBoot多线程实现定时任务 3.@EnableScheduling 与 @Scheduled

    servlet与Struts action线程安全问题分析

    1. **避免使用实例变量**:尽可能使用局部变量,局部变量只存在于方法的执行上下文中,不会被多个线程共享,因此不存在线程安全问题。 2. **使用同步控制**:通过`synchronized`关键字对关键代码块或方法进行同步,...

    java线程安全测试

    Java线程安全是多线程编程中的一个关键概念,它涉及到多个线程访问共享资源时可能出现的问题。在Java中,线程安全问题通常与并发、内存模型和可见性有关。Java内存模型(JMM)定义了如何在多线程环境下共享数据的...

    易语言实例模块——多线程模块.e

    易语言实例模块——多线程模块.e

    Linux下C语言多线程编程实例

    Linux 下 C 语言多线程编程实例 Linux 下的多线程编程是一种非常重要的技术,在实际应用中有非常广泛的应用范围。多线程编程可以大大提高程序的执行效率和响应速度。但是,多线程编程也存在一些复杂性,例如线程...

    java 多线程并发实例

    本文将基于"java 多线程并发实例"这个主题,深入探讨Java中的多线程并发概念及其应用。 首先,我们要了解Java中的线程。线程是程序执行的基本单元,每个线程都有自己的程序计数器、虚拟机栈、本地方法栈,而共享堆...

    C#.NET多线程实例6个(包括多线程基本使用,多线程互斥等全部多线程使用实例),可直接运行

    本资源包含六个C#.NET多线程的实例,涵盖了多线程的基本使用到更高级的概念,如线程互斥。以下是这些实例可能涉及的关键知识点: 1. **线程创建**:C#中创建线程主要有两种方式,一是通过`System.Threading.Thread`...

Global site tag (gtag.js) - Google Analytics