线程通信

原创 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:被守护:通过特定的锁来访问。





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

相关文章推荐

android 线程通信学习

  • 2015-05-22 09:20
  • 803KB
  • 下载

vc线程通信实现计时器

  • 2015-01-05 11:40
  • 3.47MB
  • 下载

java线程通信的三种方式

1、传统的线程通信。     在synchronized修饰的同步方法或者修饰的同步代码块中使用Object类提供的wait(),notify()和notifyAll()3个方法进行线程通信。    ...

C#线程通信

  • 2013-05-16 17:58
  • 44KB
  • 下载

进程及线程通信总结

上文我们介绍了如何建立一个简单的多线程程序,多线程之间不可避免的需要进行通信。相比于进程间通信来说,线程间通信无疑是相对比较简单的。     首先我们来看看最简单的方法,那就是使用全局变量(静态变量...
  • maopig
  • maopig
  • 2012-02-19 18:08
  • 1085

多线程之间的线程通信

线程数据通信

六、多线程 1. Java创建线程之后,直接调用start()方法和run()的区别2. 常用的线程池模式以及不同线程池的使用场景3. newFixedThreadPool此种线程池如果线程数达到最大...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

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