线程通信

原创 2016年05月31日 14:16:31

1.可见性

1.1.非原子的64位操作

没有声明为volatile的64位数值变量(double、long),JVM允许将64位的读或写划分为俩个32位操作。如果读写在不同的线程,可能会出现得到一个值的高32位和另一个值的低32位。当JVM的规范完成是,很多主流的处理器框架还不能有效地支持64为算数原子操作。

1.2.加锁

锁不仅仅是关于同步与互斥的,也是关于内存可见的。为了保证所有线程都能够看到共享的、可变的最新之,读取与写入线程必须使用公共的锁进行同步。

1.3.Volatile变量

volatile变量不会缓存在寄存器或缓存在对其他处理器隐藏的地方,读一个volatile类型的变量时,总会返回由某一线程所写入的最新值。

volatile变量对于自增自减存在不足,不能做到原子操作(读-改-写),加锁或原子类进行代替。加锁可以保证可见性与原子性,volatile变量只能保证可见性。

2.线程封闭

访问共享、可变的数据,都是要求同步,避免过多的同步的方式可以是不共享数据,该数据只能被唯一的线程访问,就不需要任何同步。线程封闭是最简单直接的实现线程安全的方式之一。

2.1.Ad-hoc线程限制

Ad-hoc是"非正式的",如餐厅中,你决定与某人谈谈业务,这就是一种"Ad-hoc"会谈。Ad-hoc是只未经过设计而得到的线程封闭行为。因为没有可见性修饰符与本地变量等语言特性协助将对象限制在目标线程上,所以这种方式是非常容易出错的。

2.2.栈限制

栈限制是线程限制的一种特例,只能通过本地变量才能触及对象。

public int calculate(Collection<Item> items){
   SortSet<Item> items0;
   int c=0;
   
   // items0 被限制在方法中,不要让其逸出
   items0 = new TreeSet<Item>(new ItemComparator());
   items0.addAll(items);
   for(Item i: items0){
      if(i.isFit())
         c++;
   }
   return c;
}

2.3.ThreadLocal

ThreadLocal允许你将每个线程与持有数值的对象关联在一起。ThreadLocal提供了get与set访问器,为每个使用它的线程维护一份单独的拷贝,所以get总是返回由当前执行线程通过set设置的最新值。

	private ThreadLocal<Connection> local = new ThreadLocal<Connection>(){
			public Connection initialValue(){
				try {
					return DriverManager.getConnection(DB_URL);
				} catch (SQLException e) {
					e.printStackTrace();
				}
				return null;
			}
	};
	public void getC() {
		local.get();
	}
#1:线程首次调用ThreadLocal.get方法时,会请求initialValue提供一个初始值。

#2:概念上可以把ThreadLocal<T>看作Map<Thread , T>,存储了与线程相关的值,不过事实上实现并非如此。当线程终止时,对应的值会被垃圾回收。

3.不可变性

不可变对象永远是线程安全的。

只要满足如下状态,一个对象才是不可变的:

#1:他的状态不能在创建后再被修改

#2:所有域都是final类型

#3:它被正确创建(创建期间没有发生this引用逸出)

4.发布对象

发布对象的必要条件依赖于对象的可见性

#1:不可变对象可以通过任意机制发布;

#2:高效不可变对象必须安全发布,如java.util.concurrent包内工具类;

#3:可变对象必须要安全发布,同时必须线程安全或被锁守护。


并发中,有效共享对象的策略:

#1:线程限制:线程独占且只能被占有它的线程修改。

#2:共享只读:多条线程并发访问,任何线程都不能修改它。共享只读对象包括高效不可变对象、可变对象。

#3:共享线程安全:对象内部进行同步,所有其他线程无需额外同步,就可以通过公共接口随意地访问它。

#4:被守护:通过特定的锁来访问。





版权声明:本文为博主原创文章,未经博主允许不得转载。

如何使用读写线程实现串口通信

  • 2009年04月16日 19:17
  • 26KB
  • 下载

Socket异步通信,线程,双端队列

  • 2010年05月21日 11:45
  • 247KB
  • 下载

【java多线程编程核心技术】3.线程间通信 -笔记总结

等待/通知机制线程与线程之间不是独立的个体,他们彼此之间可以互相通信和协作。不使用等待/通知机制实现线程通信可以通过不停地while语句轮询机制来检测某一个条件,但这样特别耗费CPU资源。(轮询间隔时...

Android跨线程通信AIDL实现简单demo

  • 2016年02月01日 01:05
  • 1.22MB
  • 下载

Caffe 初学拾遗(六) CUDA 线程通信

Original Source: http://blog.csdn.net/augusdi/article/details/12833235 一些CUDA编程的简单示例程序,笔者在此进行了整理...

QT线程通信

  • 2013年05月08日 09:45
  • 4KB
  • 下载

线程之间的通信(thread signal)

线程通信的目的是为了能够让线程之间相互发送信号。另外,线程通信还能够使得线程等待其它线程的信号,比如,线程B可以等待线程A的信号,这个信号可以是线程A已经处理完成的信号。通过共享对象通信有一个简单的实...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:线程通信
举报原因:
原因补充:

(最多只允许输入30个字)