线程同步详细讲解

1、什么状况下使用线程同步

           不少时候,咱们并不知道在什么状况下使用线程同步。在错误的状况下,就会影响性能。在正确的状况下,咱们就能够防止程序出现错误。是数据的安全获得保证。java

            线程同步通常使用在共享数据状况下,就是说共享数据,须要使用线程同步进行保护起来,使数据的安全获得保证。好比:在电子商务中,商品的库存,是共享的数据。数据库

2、Volatile变量

            相对于synchronized来讲,volatile是比较轻量级的线程同步锁。synchronized通常使用在函数上。好比:安全

public synchronized int get() {return value;}

而Volatile变量,用来确保将变量的更新操做通知到其它线程。当把变量声明为Volatile类型后,编译器与运行时都会注意到这个变量是共享的。函数

            Volatile变量一般用作某个操做完成、发生中断或者状态的标志。Volatile的语义不足以确保递增操做(count++)的原子性,除非你能确保只有一个线程对变量执行写操做。好比:性能

volatile boolean asleep;

while(!asleep)
   conutSome();

3、线程封闭

            当访问共享的可变数据时,一般须要使用同步。一种避免使用同步的方式就是不共享数据。若是仅在单线程内访问数据,就不须要同步。这种技术被称为线程封闭。线程封闭技术有两种:一栈封闭;二是ThreadLocal类。这篇文章只讲讲第二种的应用,由于是咱们常用的。spa

            ThreadLocal对象一般用于防止对可变的单实例变量或全局变量进行共享。好比,在单线程应用程序中可能会维持一个全局的数据库链接。因此,通常使用在JDBC中,经过将JDBC的连接保存到ThreadLocal对象中,每一个线程都会拥有属于本身的连接。     线程

public class DBContextHolder {
		
		private static final ThreadLocal<String> contextHolder = new ThreadLocal<String>();  
		  
		public static void setDBType(String dbType) {  
		    contextHolder.set(dbType);  
		}  
		  
		public static String getDBType() {  
		    return contextHolder.get();  
		}  
		  
		public static void clearDBType() {  
		    contextHolder.remove();  
		}  
}

调用:code

public class DynamicDataSource extends AbstractRoutingDataSource {

	// 查找当前用户上下文变量中设置的数据源
	protected Object determineCurrentLookupKey() {
		return DBContextHolder.getDBType();//这里调用
	}

	// 设置默认的数据源
	public void setDefaultTargetDataSource(Object defaultTargetDataSource) {
		super.setDefaultTargetDataSource(defaultTargetDataSource);
	}

	// 设置数据源集合.
	public void setTargetDataSources(Map targetDataSources) {
		super.setTargetDataSources(targetDataSources);
	}
}

            当某个频繁执行的操做须要一个临时对象,例如一个缓冲区,而同时又但愿避免在每次执行时都从新分配该临时对象,就可使用这项技术。对象

4、不变性

            在线程同步中,有三种性质:可见性、原子性、不变性。前面的synchronized能够确保原子性,而Volatile能够确保可见性。那么不变性,就用Final域来进行讲解。不变性主要使对象具备不可变,进而得出:不可变对象必定是线程安全的。但不可变性并不等于将对象中全部的域都声明为final类型,即便对象中全部的域都为final类型的,这个对象也仍然是可变的,由于在final类型的域中能够保存对可变对象的应用。rem

            当知足如下条件时,对象才是不可变的:

            1.对象建立之后其状态就不能修改。2.对象的全部域都是final类型。3.对象是正确建立的。

5、Java中有哪些类是线程同步的

            不少时候,咱们是直接调用Java Jdk原有的类,进行对数据的包装,进而使数据达到线程同步。如下线程安全库中的容器类提供了一下的安全发布保证:

            1.经过将一个键或者值放入Hashtable、synchronizedMap或者ConcurrentMap中,能够安全地将它发布给如何从这些容器中访问它的线程。

            2.经过将某个元素放入Vector、CopyOnWriteArrayList、CopyOnWriteArraySet、synchronizedList或synchronizedSet中。

            3.经过将某个元素放入BlockingQuete或者ConcurrentLinkedQueue中。

相关文章
相关标签/搜索