读写锁

信号量Semaphore,读写锁ReadWriteLock,计数器CountDownLatch,循环栅栏CyclicBarrier运用

不羁的心 提交于 2020-01-10 06:20:53
1.信号量Semaphore: 像synchronized, ReentrantLock等这些对临界区资源进行同步后,所有对临界区资源进行访问的线程都得串行排队,而信号量允许指定的线程数同时进行访问 demo: import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.Semaphore; public class TestSemaphore implements Runnable{ private static Semaphore semaphore = new Semaphore(5); //允许同时5个线程进行访问 不会阻塞 @Override public void run(){ try { semaphore.acquire(); System.out.println(System.currentTimeMillis() +" "+ Thread.currentThread().getName()); Thread.sleep(3000); } catch (InterruptedException e) { e.printStackTrace(); }finally { semaphore.release(

深入理解读写锁ReentrantReadWriteLock和并发容器CopyOnWriteArrayList

大兔子大兔子 提交于 2020-01-04 09:48:28
1.读写锁的介绍 在并发场景中用于解决线程安全的问题,我们几乎会高频率的使用到独占式锁,通常使用jvm提供的关键字synchronized或者juc中实现了Lock接口的ReentrantLock。它们都是独占式获取锁,也就是在同一时刻只有一个线程能够获取锁。而在一些业务场景中,大部分只是读数据,写数据很少,如果仅仅是读数据的话并不会影响数据正确性(出现脏读),而如果在这种业务场景下,依然使用独占锁的话,很显然这将是出现性能瓶颈的地方。针对这种读多写少的情况,java还提供了另外一个实现Lock接口的 ReentrantReadWriteLock(读写锁) 。读写所允许同一时刻被多个读线程访问,但是在写线程访问时,所有的读线程和其他的写线程都会被阻塞。在分析WirteLock和ReadLock的互斥性时可以按照WriteLock与WriteLock之间,WriteLock与ReadLock之间以及ReadLock与ReadLock之间进行分析。这里简要做一个归纳总结: 公平性选择:支持非公平性(默认)和公平的锁获取方式, 吞吐量还是非公平优于公平 ; 重入性:支持重入,读锁获取后能再次获取,写锁获取之后能够再次获取写锁,同时也能够获取读锁; 锁降级:遵循获取写锁,获取读锁再释放写锁的次序,写锁能够降级成为读锁 要想能够彻底的理解读写锁必须能够理解这样几个问题:1.

golang并发(1)介绍

做~自己de王妃 提交于 2020-01-04 04:46:52
概述 简而言之, 所谓并发编程是指在一台处理器上 “ 同时 ” 处理多个任务。 随着硬件的发展,并发程序变得越来越重要。 Web 服务器会一次处理成千上万的请求。平板电脑和手机 app 在渲染用户画面同时还会后台执行各种计算任务和网络请求。即使是传统的批处理问题 -- 读取数据,计算,写输出 -- 现在也会用并发来隐藏掉 I/O 的操作延迟以充分利用现代计算机设备的多个核心。计算机的性能每年都在以非线性的速度增长。 宏观的并发是 指在一段时间内 , 有多个程序在同时运行 。 并发在微观上,是指在同一时刻只能有一条指令执行,但多个程序指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段,使多个程序快速交替的执行。 并行和并发 并行 (parallel) : 指在同一时刻,有多条指令在 多个处理器 上同时执行。 并发 (concurrency) : 指在同一时刻只能有一条指令执行 , 但多个进程指令被快速的轮换执行,使得在宏观上具有多个进程同时执行的效果,但在微观上并不是同时执行的,只是把时间分成若干段, 通过 cpu 时间片轮转 使多个进程快速交替的执行。 大师曾以咖啡机的例子来解释并行和并发的区别。 并行 是两个队列 同时 使用 两台 咖啡机 (真正的多任务) 并发 是两个队列 交替 使用 一台 咖啡机 ( 假 的多任务)

Linux多线程4-2_读写锁

老子叫甜甜 提交于 2019-12-26 23:12:26
一、读写锁的概念 1、读写锁与互斥量类似,不过读写锁有更高的并行性。互斥量要么加锁要么不加锁,而且同一时刻只允许一个线程对其加锁。对于一个变量的读取, 完全可以让多个线程同时进行操作 2、pthread_rwlock_t rwlock 读写锁有三种状态,读模式下加锁,写模式下加锁,不加锁。一次只有一个线程可以占有写模式下的读写锁,但是多个线程可以同时占有读模式的 读写锁 3、读写锁在写加锁状态时,在它被解锁之前,所有试图对这个锁加锁的线程都会阻塞。读写锁在读加锁状态时,所有试图以读模式对其加锁的线程 都会获得访问权,但是如果线程希望以写模式对其加锁,它必须阻塞直到所有的线程释放锁。当读写锁一读模式加锁时,如果有线程试图以写模式对 其加锁,那么读写锁会阻塞随后的读模式锁请求。这样可以避免读锁长期占用,而写锁达不到请求。 4、读写锁非常适合对数据结构读次数大于写次数的程序,当它以读模式锁住时,是以共享的方式锁住的;当它以写模式锁住时,是以独占的模式锁 住的。 二、读写锁的初始化 1、读写锁在使用之前必须初始化 int pthread_rwlock_init(pthread_rwlock_t *restrict rwlock, const pthread_rwlockattr_t *restrict attr); 2、 使用完需要销毁 int pthread_rwlock_destroy

线程的同步

左心房为你撑大大i 提交于 2019-12-22 05:10:36
多个线程共享相同的内存时,需要确保每个线程看到一致的数据视图。 1.互斥量 可以通过使用pthread的互斥接口保护数据,确保同一时间只有一个线程访问数据,互斥量(mutex)从本质上说是一把锁, 在访问共享资源前对互斥量进行加锁,在访问完成后释放互斥量上的锁。对互斥量进行加锁后,任何其他试图再次对互斥 量进行加锁的线程将被阻塞直到当前线程释放该互斥锁。如果释放互斥锁时有多个线程阻塞,所有在该互斥锁上阻塞线程都会变成可运行状态,第一个变为运行状态的线程可以对互斥量进行加锁,其他线程将会看到互斥锁依然被锁住,只有回去再次等待它重新变成可用。在这种方式下,每次只有一个线程可以向前执行。 互斥变量用pthread_mutex_t数据类型来表示,在使用互斥变量以前,必须首先对它进行初始化,可以把它置为常量PTHREAD_MUTEX_INITIALIZER(只对静态分配的互斥量),也可以通过调用pthread_mutex_init函数进行初始化。如果动态地分配互斥量(例如通过调用malloc),那么在释放内存前需要调用pthread_mutex_destroy。 #include<pthread.h> int pthread_mutex_init(pthread_mutex_t *restrict mutex, const pthread_mutexattr_t *restrict attr

Java中的读写锁ReadWriteLock

﹥>﹥吖頭↗ 提交于 2019-12-20 09:29:59
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> ReadWriteLock 是 JDK 中的读写锁接口 ReentrantReadWriteLock 是 ReadWriteLock 的一种实现 读写锁非常适合读多写少的场景。读写锁与互斥锁的一个重要区别是读写锁允许多个线程同时读共享变量,这是读写锁在读多写少的情况下性能较高的原因。 读写锁的原则: 多个线程可同时读共享变量 只允许一个线程写共享变量 写线程正在执行写操作,禁止其他线程读写共享变量 升级与降级: ReadWriteLock 不支持锁的升级。即线程先获得读锁,再获取写锁,这样会导致死锁 ReadWriteLock 支持锁的降级。即先获取写锁,再获取读锁,释放写锁,释放读锁 ReadWriteLock 中只有写锁支持条件变量,读锁调用 newCondition() 方法,会抛出 UnsupportedOperationException 异常 读写锁的应用示例: package constxiong.interview; import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.ReadWriteLock; import java.util.concurrent.locks

java数据结构类--笔记

谁都会走 提交于 2019-12-20 04:12:32
程序的灵魂是算法。提到算法,肯定离不开数据结构。今天就聊一聊java中的和数据结构相关的类。 java.util包 concurrent包 里面是和并发编程相关的类 主要是:原子类–锁--并发的数据结构类【队列,链表,哈希…】 atomic—原子类【 https://blog.csdn.net/boom_man/article/details/78352722 】 locks—锁 Lock锁和同步块的区别 1.同步块只能包含在一个方法内----而lock()和unlock()操作却可以在跨越多个不同的方法使用。 2.同步块不支持公平性,任一个线程都能获取已经被释放的锁,不能指定优先权。但我们却可以使用Lock API指定公平属性从而实现公平性。它能确保等待时间最长的线程优先获取锁。 3.当一个线程不能访问同步块时,它会被阻塞住。而 Lock API提供的有 tryLock()方法,使用该方法,只有在锁不被其他线程持有且可用时,才会真正获取锁。这将极大地降低阻塞时间。 4.那些获取访问同步块的等待线程不能被中断,Lock API提供了一个 lockInterruptbly()方法,当线程正在等待锁时,该方法可以用于中断该线程。’ 接口 ReadWriteLock读写锁 ReadWriteLock维护一对关联锁,一个用于只读操作,一个用于写入。只要没有写入程序

026 UNIX再学习 -- 线程同步

六月ゝ 毕业季﹏ 提交于 2019-12-18 22:05:52
一、为什么要线程同步 当多个控制线程共享相同的内存时,需要确保每个线程看到一致的数据视图。如果每个线程使用的变量都是其他线程不会读取和修改的,那么就不存在一致性问题。同样,如果变量时只读的,每个线程同时读取该变量也不会有一致性问题。但是, 当一个线程可以修改的变量,其他线程也可以读取或者修改的时候,我们就需要对这些线程进行同步,确保它们在访问变量的存储内容时不会访问到无效的值 。 当一个线程修改变量时,其他线程在读取这个变量时可能会看到一个不一致的值。在变量修改时间多于一个存储器访问周期的处理器结构中,当存储器读与存储器写这两个周期交叉时,这种不一致就会出现。当然,这种行为是与处理器体系结构相关的,但是可移植的程序并不能对使用何种处理器体系结构做出任何假设。 上图中描述了两个线程读写相同变量的假设例子。在这个例子中,线程 A 读取变量然后给这个变量赋予一个新的数值,但写操作需要两个存储器周期。当线程 B 在这两个存储器写周期中间读取这个变量时,它就会得到不一致的值。 为了解决这个问题,线程不得不使用锁,同一时间只允许一个线程访问该变量。 如果线程 B 希望读取变量,它首先要获取锁。同样,当线程 A 更新变量时,也需要获取同样的这把锁。这样,线程 B 在线程 A 释放锁以前就不能读取变量。 总结一下, 多线程共享进程中的资源,多个线程同时访问相同的共享资源时,需要相互协调

Java中各种锁机制的介绍

馋奶兔 提交于 2019-12-13 12:46:40
本文内容 在读很多并发文章中,会提及各种各样锁如公平锁,乐观锁等等,这篇文章介绍各种锁的分类。介绍的内容如下: 1.公平锁 / 非公平锁 2.可重入锁 / 不可重入锁 3.独享锁 / 共享锁 4.互斥锁 / 读写锁 5.乐观锁 / 悲观锁 6.分段锁 7.偏向锁 / 轻量级锁 / 重量级锁 8.自旋锁 上面是很多锁的名词,这些分类并不是全是指锁的状态,有的指锁的特性,有的指锁的设计,下面总结的内容是对每个锁的名词进行一定的解释。 公平锁 / 非公平锁 公平锁 公平锁是指多个线程按照申请锁的顺序来获取锁。 非公平锁 非公平锁是指多个线程获取锁的顺序并不是按照申请锁的顺序,有可能后申请的线程比先申请的线程优先获取锁。有可能,会造成优先级反转或者饥饿现象。 对于 Java ReentrantLock 而言,通过构造函数指定该锁是否是公平锁,默认是非公平锁。非公平锁的优点在于吞吐量比公平锁大。 对于 Synchronized 而言,也是一种非公平锁。由于其并不像 ReentrantLock 是通过 AQS 的来实现线程调度,所以并没有任何办法使其变成公平锁。 可重入锁 / 不可重入锁 可重入锁 广义上的可重入锁指的是可重复可递归调用的锁,在外层使用锁之后,在内层仍然可以使用,并且不发生死锁(前提得是同一个对象或者class),这样的锁就叫做可重入锁。 ReentrantLock 和

Java并发编程初级篇(十四):使用读写所实现同步机制

蓝咒 提交于 2019-12-12 19:43:03
【推荐】2019 Java 开发者跳槽指南.pdf(吐血整理) >>> Java API除了提供Lock()接口之外,还为我们提供了一个读写锁接口ReadWriteLock,使用这个锁的实现类ReentrantReadWriteLock可以让我们把读锁和写锁进行分离,对同步数据进行修改的时候使用写锁,这时候其他需要获取写锁的线程会被挂起,同时使用读锁的线程也会被挂起。而读取数据的时候使用读锁,这时候使用读锁的线程可以并发访问,以提高效率。 public interface ReadWriteLock { /** * Returns the lock used for reading. * * @return the lock used for reading. */ Lock readLock(); /** * Returns the lock used for writing. * * @return the lock used for writing. */ Lock writeLock(); } 我们模拟一个修改价格的例子,来看一下读锁与写锁是如何使用的。 创建一个价格类,里面两个商品的价格以及一个读写锁。在修改价格的方法里我们使用写锁,在读取商品价格的方法里我们使用读锁。修改商品价方法休眠两秒来模拟修改价格的过程,并打印修改价格信息。 public class