两个线程调用临界资源输出打印,如何实现互斥?<互斥的例子>

 

参考网址:

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);
    }

}

 

相关文章: