java线程同步

当谈起多线程的时候 都关注什么

多线程同步
同步一词的含义就是 协同步调,按预定的先后次序进行运行 ,本来多线程是并发的,但是得按照一定规则 来执行。
所谓的线程切换/互斥控制/线程同步 差不多都是一个意思。

关于互斥同步一词,同步是按照一定规则来执行,是目的。互斥是实现同步的一种手段。所以同步机制的目的是多线程访问共享数据或执行同一代码块的时候,多个线程只能串行的进入。。以保证程序的正确性。

实现互斥同步有三种机制:
分别是临界区,互斥量和信号量。这些本质上都是通过加锁来实现的。

临界区:
synchronized关键字 ReentrantLock 都是一种临界区的实现,临界区的含义也体现在api上。

synchronized关键字:
当遇到同步边界,monitorrender指令尝试获取对象的锁。如果对象没有被锁定,当前线程就会持有该锁, 进入同步方法块执行。 否则进入阻塞状态。直到对象锁被另一个线程释放。

Renentrantlock:
juc包中 重入锁lock和unlock方法。 renentrantlock增加了一些高级功能。 锁可以绑定多个条件。 等待可中断 ,可实现公平锁。

线程的阻塞和唤醒 :
synchronized 机制下 wait/notify/notifyAll 可实现线程间的等待和唤醒。来控制多线程的执行流程。
ReentrantLock 下使用condition条件变量。

加锁代码示例:
synchronized (ThreadLock.WAIT_OBJECT) {
    ThreadLock.LOGGER.info("do something。。。。");
}

ReentrantLock objectLock = new ReentrantLock();
   objectLock.lock();
   ThreadLock.LOGGER.info("do something。。。。");
   objectLock.unlock();
......

当遇到同步边界的时候,需要对加锁的对象进行同步检查,同步边界内的代码只允许某一条线程A进入.
满足以下两个条件之一 同步代码块才允许其他线程访问:
线程A退出了同步边界
通过wait等方法 或者 condition条件变量 进入了阻塞状态

其他的线程控制工具:
对于三者的控制效果,不必手工通过临界区的方式来操作了。
包括Semaphore、CountDownLatch CyclicBarrier 这三种都是concurrent包下的。  
当然还有 java.util.concurrent.atomic子包。基于原子操作的,有别于 之前的线程同步方法。

线程间数据传递的方式:
共享变量。
Callable 算是一种 可以有线程执行的返回值。

atomic原子操作包:
我们都知道在多线程环境下,对于更新对象中的某个属性、更新基本类型数据、更新数组(集合)都可能产生脏数据问题
JDK1.5的版本中为我们提供了java.util.concurrent.atomic原子操作包。所谓“原子”操作,是指一组不可分割的操作:操作者对目标对象进行操作时,要么完成所有操作后其他操作者才能操作;要么这个操作者不能进行任何操作;
java.util.concurrent.atomic原子操作包为我们提供了四类原子操作:原子更新基本类型,原子更新数组,原子更新引用和原子更新字段。
sun.misc.atomic是JDK提供的乐观锁的支持。AtomicInteger是一个标准的乐观锁实现。

乐观锁与悲观锁:
乐观锁假定“冲突不一定会出现”,如果出现冲突则进行重试,直到冲突消失.
悲观锁是一种独占锁,它假设的前提是“冲突一定会发生”,而独占意味着“其它即将执行这段代码的其他线程”都将进入“阻塞”/“挂起”状态。是的,synchronized关键字就是java对于悲观锁的实现

基于乐观锁的实现。包括(但不限于):
java.util.concurrent.atomic包中的原子数据操作。
java.util.concurrent包中的线程安全的数据结构等等。
renentrantlock应该基于乐观锁。synchronized关键字使用的悲观锁。

但关于两者的性能,在jdk1.6 之后因为做了许多锁的优化措施 所以性能上持平了。以后虚拟机在性能改进上也会偏向原生的synchronized。

关于可重入锁:
可重入锁java里面内置锁(synchronized)和Lock(ReentrantLock)都是可重入锁,但是实现机制不一样。可重入锁又叫做递归锁。

ReentrantLock的实现机制:
为每个锁关联一个获取计数器和一个所有者线程,当计数值为0的时候,这个锁就没有被任何线程只有.
当线程请求一个未被持有的锁时,JVM将记下锁的持有者,并且将获取计数值置为1,如果同一个线程再次获取这个锁,技术值将递增,退出一次同步代码块,计算值递减,当计数值为0时,这个锁就被释放.ReentrantLock里面有实现

synchronized的实现机制:
检查指向锁记录指针是否指向当前线程栈帧中的锁记录。 如果是 则当前线程已经获取该锁。

你可能感兴趣的:(多线程,线程同步,java,Java基础)