`
maximilian_kevin
  • 浏览: 1756 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
最近访客 更多访客>>
社区版块
存档分类
最新评论

线程安全学习笔记(二)

阅读更多
两个常来说明volatile的例子:
例子1:
package com.maximilian.www;

public class MyTestThread extends Thread
{
	volatile public static int count = 0;
	private  int countPerThread = 0;
	private int _loopTimes=0;
	private int _threadId;
	public MyTestThread(int threadId ,int loopTimes)
	{
		_threadId = threadId;
		_loopTimes = loopTimes;
	}
	@Override
    public void run()
    {
	    while(_loopTimes > 0)
	    {
	    	_loopTimes--;
	    	count++;
	    	countPerThread++;
	    }
	 }
	public void printNum()
	{
		System.out.println("Thread "+_threadId+" count "+countPerThread+" times!");
	}

}

测试类:

package test;

import java.util.Vector;

import com.maximilian.www.MyTestThread;



public class MyTest
{
	private static int loopTimes=1000;
	private static int threadNum = 2;
	private static int threadId;
	private static Vector<MyTestThread> threads = new Vector<MyTestThread>();
	public static void main (String [] args)
	{
	    for(threadId=0;threadId < threadNum ;threadId++)
	    {
	    	MyTestThread t = new MyTestThread(threadId, loopTimes);
		    threads.add(t);
	    }
	    for(Thread t:threads)
	    {
	    	t.start();
	    }
	    for(Thread t:threads)
	    {
	    	try
            {
	            t.join();
            } catch (InterruptedException e)
            {
	            // TODO Auto-generated catch block
	            e.printStackTrace();
            }
	    }
	    System.out.println("All threads count "+MyTestThread.count+" times!!");
	    for(MyTestThread t:threads)
	    {
	    	t.printNum();
	    }   
	}
}

输出结果:
All threads count 1698 times!!
Thread 0 count 1000 times!
Thread 1 count 1000 times!

例子2:
package com.maximilian.www;

public class MyTestThread2 extends Thread
{
	volatile private static int upperLimit = 5;
	volatile private static int lowerLimit = 2;
	private int _threadId;
	public MyTestThread2(int threadId )
	{
		_threadId = threadId;
	}
	@Override
	public void run()
	{
		while(upperLimit>lowerLimit)
		{
			if(_threadId % 2 == 0)
			{
				setUpperLimit(3);
			}
			else 
			{
				setLowerLimit(4);
			}
		}
	}
	public void setUpperLimit(int upper)
	{
		if(lowerLimit <= upper)
		{
			upperLimit = upper;
		}		
		else 
		{
			lowerLimit = 2;
		}
	}
	public void setLowerLimit(int lower)
	{
		if(upperLimit >= lower)
		{
			lowerLimit = lower;
		}		
		else 
		{
			upperLimit = 5;
		}
	}
	public static int getUpperLimit()
	{
		return upperLimit;
	}
	public static int getLowerLimit()
	{
		return lowerLimit;
	}

}

测试类:
package test;

import java.util.Vector;

import com.maximilian.www.MyTestThread2;

public class MyTest2
{
	private static int threadNum = 2;
	private static int threadId;
	private static Vector<MyTestThread2> threads = new Vector<MyTestThread2>();
	public static void main (String [] args)
	{
		
	    for(threadId=0;threadId < threadNum ;threadId++)
	    {
	    	MyTestThread2 t = new MyTestThread2(threadId);
		    threads.add(t);
	    }
	    for(Thread t:threads)
	    {
	    	t.start();
	    }
	    for(Thread t:threads)
	    {
	    	try
            {
	            t.join();
            } catch (InterruptedException e)
            {
	            // TODO Auto-generated catch block
	            e.printStackTrace();
            }
	    }
        System.out.println("lowerLimit:"+MyTestThread2.getLowerLimit()+"\n upperLimit:"+MyTestThread2.getUpperLimit());
	}
}

测试结果:
lowerLimit:4
upperLimit:3

从上面的两个例子可以看出, volatile修饰的变量至少从操作的角度来看不是线性进行的。
一般的普通的对变量的操作过程:

多线程的情况下就会发生:

通过上面例子,我们可以知道,即使对变量进行了volatile申明还是有上面图中的现象寻在,例子1中计数操作有线程的操作直接被覆盖,对于例子2两个有内在联系的变量的操作也是因为这种读取-修改-更新的非原子性导致的,有点写逻辑的时候因为延时出现的竞争冒险现象(写逻辑出身伤不起)。
那么volatile加了有什么作用的?对volatile变量在线程本地工作区中不做缓存,对volatile的读写总是指向堆中的引用。这个类似于告诉线程这个变量在本身的存储空间上的值是不可信的,每次要用到就要去公共内存上读取,并且会要求线程在修改完成后及时更新住内存(有些操作对对象连续操作可能不会及时每变一次更新),这样就保证了线程的操作只要完成就可以被其他线程看到。
Volatile对于新手来说比较难用,但是因为他的性能好于syncronized以及没有锁的同步,在高手手里还是个宝。
应用场景:
1. 状态标志指示发生了一个重要的一次性事件,例如完成初始化或请求停机;
2. 一次性安全发布。在1.5以后貌似是可以解决双重检查锁定单例中的问题。
http://www.cnblogs.com/melode11/archive/2008/09/28/1301114.html
http://www.ibm.com/developerworks/cn/java/j-dcl.html
3. 独立观察,定期 “发布” 观察结果供程序内部使用。
4. volatile bean 模式。
5. 结合volatile和syncronized的开销较低的读-写锁策略。
分享到:
评论

相关推荐

    Java线程编程学习笔记(二)

    这篇“Java线程编程学习笔记(二)”很可能是对Java并发编程深入探讨的一部分,特别是涉及多线程示例的实践应用。我们将从标题、描述以及标签来推测可能涵盖的知识点,并结合"Multi-Threads Demo"这一压缩包文件名来...

    JAVA并发编程实践-线程安全-学习笔记

    在Java并发编程中,线程安全是一个至关重要的概念,它涉及到多线程环境下对共享数据的正确管理和访问。线程安全意味着当多个线程同时访问一个对象或数据时,对象的状态能够保持一致性和完整性,不会因为并发导致数据...

    java线程学习笔记

    Java线程学习笔记涉及了Java多线程编程的多个关键知识点,本篇知识点整理将详细解释每个概念及其在Java中的实现方式。 基本知识部分包含了Java线程编程的基础内容,它们是并发编程的基石。 任务Runnable是一个接口...

    线程技术学习笔记.docx

    为了实现线程安全,Java提供了多种同步机制,如`synchronized`关键字,它可以确保共享资源在同一时间只能被一个线程访问,从而避免数据不一致的问题。线程安全应优先于性能考虑,因为确保结果正确性是更重要的。 ...

    马士兵多线程训练营笔记

    4. **线程安全的数据结构**:Java集合框架中的线程安全类,如Vector、ArrayList、LinkedList、HashMap、ConcurrentHashMap的区别和使用场景。 5. **线程通信**:wait()、notify()、notifyAll()方法的使用,以及在...

    马士兵多线程笔记.zip

    8. **并发集合**:Java的并发包(java.util.concurrent)提供了线程安全的集合,如ConcurrentHashMap、CopyOnWriteArrayList等,它们在内部实现了高效的并发控制。 9. **线程中断**:通过Thread.interrupt()方法...

    Java中线程同步和线程协作学习笔记

    线程同步的主要目标是解决线程安全问题,即在多线程访问共享资源时避免数据的混乱,保证程序的可再现性。这通常涉及到临界资源的管理,如打印机、共享变量或数据结构。在Java中,线程同步可以通过使用同步锁来实现,...

    多线程学习笔记与学习

    多线程技术是计算机编程中的一个重要概念,尤其在现代多核处理器的环境下,多线程能够充分利用硬件资源...在实际编程中,开发者需要根据具体需求选择合适的线程模型,并注重线程安全和资源管理,以实现最优的系统性能。

    python线程教程,python线程学习笔记.doc

    在本文中,我们将深入探讨Python线程的基础知识,包括线程如何访问全局变量、线程安全问题、线程同步以及互斥锁的使用。 首先,让我们看看线程如何访问全局变量。在Python中,一个进程内的所有线程共享全局变量。...

    多线程程序设计——笔记

    多线程程序设计学习笔记,内容详尽、实用,本笔记中将详细介绍多线程程序设计的基本概念、线程的创建和管理、线程同步和通信、线程安全性等方面的知识点。 一、线程的基本概念 在多线程程序设计中,线程是操作系统...

    java基础:多线程学习笔记

    在Java的多线程学习笔记中,通常会涉及到以下几个核心知识点: 1. **多线程的概念**:多线程是指在单个进程中同时运行多个线程来执行不同的任务。Java提供了丰富的API支持多线程编程,使得开发者可以方便地创建、...

    Python3的多线程学习笔记[定义].pdf

    本篇学习笔记主要涵盖了线程基础、threading模块的使用以及线程同步控制。 首先,线程是操作系统分配CPU执行时间的基本单位,一个进程可以包含多个线程。在Python3中,线程的状态主要包括新建、就绪、运行、死亡、...

    C++多线程学习笔记1

    这份"C++多线程学习笔记1"涵盖了基础到进阶的多线程概念,旨在帮助初学者快速掌握这一关键技能。 首先,C++11引入了对多线程的支持,引入了`&lt;thread&gt;`库,使得创建和管理线程变得简单。创建一个新的线程可以使用`...

    学习笔记多线程Unix编程

    在深入探讨多线程Unix编程之前,...学习笔记中的内容可能涵盖了以上各个知识点的实例、代码示例和解析,帮助你理解和实践多线程Unix编程。通过不断实践和学习,你将能够熟练地在Unix环境中编写高效的多线程应用程序。

    JUC多线程学习个人笔记

    2. **并发集合**:JUC提供了线程安全的集合类,如ConcurrentHashMap、ConcurrentLinkedQueue等。这些集合在多线程环境中可以保证数据的一致性和完整性,避免了传统集合在并发操作时可能出现的不一致状态。 3. **...

    java多线程学习笔记

    - **ThreadLocal**:每个线程都有自己独立的副本,互不干扰,避免了线程安全问题。 8. **线程池** - **ExecutorService**:线程池接口,提供创建、管理和关闭线程池的方法。 - **Executors**:静态工厂方法,...

    多线程学习笔记.docx

    在多线程编程中,进程和线程是两个核心概念。进程是操作系统资源分配的基本单位,每个独立执行的程序都对应一个...在实际开发中,合理利用线程池、同步机制和异常处理可以有效避免线程安全问题,提高程序的并发性能。

    com学习笔记

    在COM学习笔记中,主要涉及的是COM线程管理的概念,包括线程单元(Thread Apartments,简称TA)以及线程如何与COM对象交互。 线程单元是COM中管理线程与对象交互的核心机制。它是一个逻辑上的容器,确保同一单元内...

    C#多线程笔记学习指南

    本篇笔记将深入探讨C#多线程的基本概念、操作方法以及注意事项。 首先,我们要理解多线程的基本概念。线程是程序执行的最小单位,每个线程都有自己的执行路径和栈空间,但它们共享同一块堆内存。因此,线程间的通信...

    Java 学习笔记Java学习笔记

    Java是一种广泛使用的面向对象的编程语言,由Sun Microsystems(现为Oracle公司的一部分)于1995年发布。...Java学习笔记涵盖了这些核心知识点,通过深入学习和实践,你可以逐步掌握Java编程,并应用于实际项目开发中。

Global site tag (gtag.js) - Google Analytics