线程的同步和互斥:
线程的同步:指多线程通过特定的手段(如互斥量)来控制线程之间的执行顺序。
线程的互斥:实指对共享资源的约束访问。多线程环境中,某些资源只允许一个线程使用,这类资源成为临界资源,线程之间的关系就表现为互斥的。
线程之间的同步和互斥是通过操作系统的信号量和PV操作原语来实现的。
互斥体(Mutex):
表现互斥现象的数据结构,也被当作二元信号灯。一个互斥基本上是一个多任务敏感的二元信号,它能用作同步多任务的行为,它常用作保护从中断来的临界段代码并且在共享同步使用的资源。
信号量(Semaphore):
是在多线程环境下使用的一种设施,是可以用来保证两个或多个关键代码段不被并发调用。在进入一个关键代码段之前,线程必须获取一个信号量;一旦该关键代码段完成了,那么该线程必须释放信号量。其它想进入该关键代码段的线程必须等待直到第一个线程释放信号量。
JDK的Semaphore类对它自己的解释是:A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each {@link #acquire} blocks if necessary until a permit is available, and then takes it. Each {@link #release} adds a permit, potentially releasing a blocking acquirer.
PV原语:
PV原语通过操作信号量来处理进程间的同步与互斥的问题。其核心就是一段不可分割不可中断的程序。信号量是由操作系统来维护的,用户进程只能通过初始化和两个标准原语(P、V原语)来访问。初始化可指定一个非负整数,即空闲资源总数。
P原语:P是荷兰语Proberen(测试)的首字母。为阻塞原语,负责把当前进程由运行状态转换为阻塞状态,直到另外一个进程唤醒它。操作为:申请一个空闲资源(把信号量减1),若成功,则退出;若失败,则该进程被阻塞;
V原语:V是荷兰语Verhogen(增加)的首字母。为唤醒原语,负责把一个被阻塞的进程唤醒,它有一个参数表,存放着等待被唤醒的进程信息。操作为:释放一个被占用的资源(把信号量加1),如果发现有被阻塞的进程,则选择一个唤醒之。
临界区:
不论是硬件临界资源,还是软件临界资源,多个进程必须互斥地对它进行访问。每个进程中访问临界资源的那段代码称为临界区(Critical Section)(临界资源是一次仅允许一个进程使用的共享资源)。每次只准许一个进程进入临界区,进入后不允许其他进程进入。
监视器:
在Java中,任何一个对象都有一个监视器,来排斥共享访问临界区域的代码。这些临界区可以是一个方法或者是一段代码块,这些临界区域作为同步块。线程只有获取该监视器才能执行同步块的代码。当一个线程到达这块代码是,首先等待来确定是否其他线程已经释放这个监视器。监视器除了排斥共享访问,还能通过Wait和Notify来协调线程之间的交互。
公平锁和非公平锁:
ReentrantLock有一个带布尔型参数的构造函数,接受可选的“公平”参数。公平锁使线程按照请求锁的顺序依次获得锁;而不公平锁则允许讨价还价,在这种情况下,线程有时可以比先请求锁的其他线程先得到锁。
性能开销:
4CPU情况下,吞吐量的比较:
单CPU情况下:
使用Lock比使用synchronize要注意的地方在:
1.使用Lock,你必须手动的在finally块中释放锁。锁的获得和释放是不受JVM控制的,如果造成语意级别的死锁,jstack等工具是无法自己识别出来的。
2.当 JVM 用 synchronized 管理锁定请求和释放时,JVM 在生成线程转储时能够包括锁定信息。这些对调试非常有价值,因为它们能标识死锁或者其他异常行为的来源。Lock 类只是普通的类,JVM 不知道具体哪个线程拥有 Lock 对象。
总之,Lock提供了在多线程争用的情况下更好的并发性,但这是以牺牲一定的可维护性为代价的。
ReentrantLock是“一个可重入的互斥锁 Lock,它具有与使用 synchronized 方法和语句所访问的隐式监视器锁相同的一些基本行为和语义,但功能更强大。
ReentrantLock将由最近成功获得锁,并且还没有释放该锁的线程所拥有。当锁没有被另一个线程所拥有时,调用lock的线程将成功获取该锁并返回。如果当前线程已经拥有该锁,此方法将立即返回。可以使用 isHeldByCurrentThread() 和 getHoldCount() 方法来检查此情况是否发生。
几种常用队列:
ArrayBlockingQueue:最常用
LinkedBlockingQueue:不会满的
SynchronousQueue:size==0的
PriorityBlockingQueue
CompletionService (BlockingQueue + Executor)
TransferQueue (JDK 7中更快的SynchronousQueue)
Queue接口:
remove()和poll()的比较:Method remove differs from {@link #poll poll} only in that it throws an exception if this queue is empty.
add()和offer()的比较:When using a capacity-restricted queue, method offer is generally preferable to {@link #add}, which can fail to insert an element only by throwing an exception.
BlockingQueue接口:
poll()和take()的比较:poll允许指定等待时间参数(specified wait time if necessary for an element to become available)。
offer()和put()比较:同上,offer允许指定等待时间参数。
使用BlockingQueue的时候,尽量不要使用从Queue继承下来的方法,否则就失去了Blocking的特性了。
Condition的await()/signal()/signalAll()提供了语义锁的等待和唤醒机制:
Condition xxxCondition = lock.newCondition();
不要在Lock和Condition上使用wait、notiffy、notifyAll方法。
CAS的lock-free算法:
class Counter {
private AtomicInteger max = new AtomicInteger();
public void set(int value) {
for (;;) {
int current = max.get();
if (value > current) {
if (max.compareAndSet(current, value)) {
break;
} else {
continue;
}
} else {
break;
}
}
}
public int getMax() {
return max.get();
}
}
通常由三个部分组成:
1、循环
2、CAS
3、回退
其中,对于compareAndSet(int expect, int update)方法的说明:Atomically sets the value to the given updated value if the current value {@code ==} the expected value.
关于非阻塞算法可以参看这里。
分享到:
相关推荐
在缓冲区问题中,我们可以看到多个进程之间的同步和互斥关系。例如,在问题 1 中,我们有一个输入进程和一个输出进程,它们共享一个缓冲区。缓冲区中每次只能存放一个数,输入进程负责输入数据,而输出进程负责输出...
g: 利用互斥量来解决线程同步互斥问题 h: problem1 生产者消费者问题 (1生产者 1消费者 1缓冲区) problem1 more 生产者消费者问题 (1生产者 2消费者 4缓冲区) problem2 读者与写着问题 I: 信号量 semaphore ...
操作系统实验是计算机科学教育中的重要组成部分,它帮助学生理解和掌握操作系统的基本原理,特别是多线程同步与互斥的概念。在Java编程环境下,这些概念可以通过实际的代码实现来深入理解。 多线程是现代操作系统中...
在Java编程中,线程同步和互斥是多线程编程中的重要概念,它们用于解决多个线程同时访问共享资源时可能出现的问题。本项目通过一个生产者消费者问题的实例,展示了如何在Java中实现线程间的同步与互斥。 生产者消费...
在Linux操作系统中,多进程和多线程是两种并发执行的方式,它们在处理并发问题时,经常需要进行同步和互斥操作,以确保数据的一致性和程序的正确性。本篇将详细介绍这两种并发模型以及如何在Linux环境中实现同步互斥...
进一步,文档深入探讨了线程同步与互斥的必要性,解释了互斥锁(mutex)和信号量(semaphore)的工作原理及其在多线程编程中的应用。互斥锁保证了同一时间只有一个线程可以访问共享资源,而信号量则通过计数机制控制...
在Java、C++、Python等支持多线程的编程语言中,线程同步和互斥是确保程序正确性和数据一致性的重要手段。 线程是指在单一进程内并行执行的多个控制流。在多核处理器系统中,这些线程可以同时在不同的核心上运行,...
(1) 通过编写程序实现进程同步和互斥,掌握有关进程(线程)同步与互斥的原理,以及解决进程(线程)同步和互斥的算法,从而进一步巩固进程(线程)同步和互斥等有关的内容。 (2) 了解Windows2000/XP中多线程的...
掌握线程创建和终止,加深对线程和进程概念的理解,会用同步与互斥方法实现线程之间的通信。 三、内容和要求 软件界面上点“创建线程” 按钮,创建三个生产者线程(P1,P2,P3)和两个消费者线程(C1,C2),生产者...
小实验二:使用Windows互斥信号量操作函数解决上述线程并发问题,并分析、尝试和讨论线程执行体中有关信号量操作函数调用的正确位置 小实验三:根据同步机制的Peterson软件解决方案尝试自己编程实现线程同步机制和...
在Windows等操作系统下,使用的VC、VB、java或C等编程语言,采用进程(线程)同步和互斥的技术编写程序实现生产者-消费者问题或哲学家进餐问题或读者-写者问题或自己设计一个简单进程(线程)同步和互斥的实际问题。
然而,多线程环境下可能会出现数据竞争、死锁等问题,因此需要使用同步和互斥机制来保证线程安全。 一、线程同步 线程同步是指在多线程环境中,控制多个线程按特定顺序执行或协同工作的一种机制。常见的线程同步...
学习多线程同步和互斥不仅对理解操作系统原理至关重要,也是编写高效、稳定的多线程应用程序的基础。Mutex和AutoResetEvent只是C#中众多同步原语的一部分,还包括Semaphore、Monitor、SemaphoreSlim等。理解并熟练...
Linux系统编程——线程同步与互斥:读写锁,相关教程链接如下: http://blog.csdn.net/tennysonsky/article/details/46485735
在C/C++编程中,线程同步和互斥是多线程编程中的核心概念,用于保证并发执行的线程之间能正确地共享资源,避免数据竞争和其他潜在的问题。本资料包"线程同步+互斥)c&c++.rar"显然是针对Windows平台,提供了相关的...
在这个“多线程编程和操作系统线程同步互斥演示”中,作者可能创建了一个或多个人工场景,展示了如何在VC++环境中使用多线程,并且演示了线程同步和互斥的实践应用。这可能涉及到以下几个方面: 1. **线程创建**:...
4. Windows 2000/XP 中的同步对象:Windows 2000/XP 中提供了多种同步对象,如事件、信号量、互斥锁、临界区等,以便实现进程之间的同步和互斥。 5. Critical Section:Critical Section 是 Windows 2000/XP 中的一...
为了确保数据的一致性和程序的正确性,必须采取措施来实现线程之间的同步与互斥。 #### 关键段(Critical Section) 在Windows平台下,解决多线程同步互斥问题的一种常用方法是使用关键段(Critical Section)。关键...
通过对生产者-消费者问题的学习,我们了解了如何在多进程或多线程环境中通过信号量和互斥锁来实现进程间的同步与互斥。这个问题不仅是操作系统课程中的一个重要知识点,也是实际软件开发中经常遇到的场景之一。理解...