两个线程调用临界资源输出打印,如何实现互斥?<互斥的例子>
参考网址:
https://blog.csdn.net/zbw18297786698/article/details/53435248
| 心得体会: |
|
利用Thread创建两个线程,调用方法slep()会使调用它的线程挂起以百万分之一为单位的制定周期, 该方法抛出一个InterruptedExcption,在try/catch中调用。 sleep(10)使当前线程进入停滞状态,以留给一定时间给其他线程执行的机会 线程一和线程二调用<final Outputer>类的output()方法打印字符,调用临界资源 出现不正常的情况: |
非互斥情况:
| 抓图1: | |
| 通过声明函数为 synchronized 的方式,只能实现函数体的互斥。要确保资源使用的互斥,即同一时刻只能有一个线程使用该资源,可以将操作资源 A 的语句放入 synchronized 代码块 | |
互斥情况:
| 抓图2: |
实现代码如下
//内部类
final class Outputer{
private String _x="";
public void output(String name){
int len = name.length();
synchronized(_x) {
for(int i=0;i<len;i++){
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
/*************************************************************************************************/
public class TestThread {
static final Outputer outputer = new Outputer();
public static void main(String[] args) {
new TestThread().init();
}
private void init(){
/*************************************************************************************************/
new Thread(new Runnable(){
@Override
public void run() {
while(true){
try {
Thread.sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
outputer.output("aaaa");
}
}
}).start();
/*************************************************************************************************/
new Thread(new Runnable() {
@Override
public void run() {
while(true) {
try {
Thread.sleep(10);
}catch(InterruptedException e) {
e.printStackTrace();
}
outputer.output("bbbb");
}
}
}).start();
}
}
二、 顺序控制 实现同步
生产者与消费者间的关系
参考网址:
https://juejin.im/entry/5a74735ff265da4e7a782ae4
|
心得体会: |
|
|
多个线程通过协作队相同资源进行操作,是为同步。 代码实现一个生产者与一个消费者,生产者负责生产资源并放在盒子,盒子容量够大,消费者从盒子取走资源,如果盒子里没有资源,则需要等待 问题会涉及到互斥和同步。
示例中创建了两个线程:消费者线程和生产者线程。生产者不断生产资源,而消费者不断消耗资源,为了验证消费者在资源为零时会阻塞到生产者再次产生资源为止,这里让消费者的消耗速度大于生产者的生产速度,并且将初始的资源数 resourceCount 设置为 3
使用Condition对象 Java 中锁的实现较为特殊,应该先获得互斥锁,再判断是否满足使用条件,如果不满足条件,则使用 Condition 对象的 await() 方法放弃已获得的互斥锁,并阻塞到条件满足为止
在 Java 中通过调用 Lock 对象的 newCondition() 方法来创建 Condition 对象,当获得互斥锁之后,如果条件不满足,那么使用 Condition 对象的 await() 方法来放弃已经获得的锁,以便其它线程使用共享资源。同时,当前线程会开始等待,一旦其它线程调用了 Condition 对象的 signalAll() 方法,当前线程就会收到通知,再次检查条件,如果满足就会等待获取互斥锁 |
| 抓图3: | |
//实现代码:
package operate;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Synchronization {
private static int resourceCount = 3;
private static Lock boxLock = new ReentrantLock();
private static Condition resourceAvailable = boxLock.newCondition();
public static void main(String[] args) {
Thread producer = new Thread(() -> {
try {
while (true) producer();
} catch (InterruptedException e) {}
});
Thread consumer = new Thread(() -> {
try {
while (true) consumer();
} catch (InterruptedException e) {}
});
producer.start();
consumer.start();
}
public static void producer() throws InterruptedException {
boxLock.lock();
resourceCount++;
resourceAvailable.signalAll();
System.out.println("Producer: boxSize + 1 = " + resourceCount);
boxLock.unlock();
Thread.sleep(1000);
}
public static void consumer() throws InterruptedException {
boxLock.lock();
try {
while (resourceCount == 0)
resourceAvailable.await();
resourceCount--;
System.out.println("Consumer: boxSize - 1 = " + resourceCount);
}
finally {
boxLock.unlock();
}
Thread.sleep(500);
}
}