1. 程式人生 > >011.多執行緒-lock鎖

011.多執行緒-lock鎖

類似於上一篇使用synchronized實現生產者與消費者間的通訊,
這裡使用lock鎖來實現。

package cn.qbz.thread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @Author: 花生米
 * @Date: 2018/11/15 22:04
 */
public class LockTest {

    public static
void main(String[] args) { Student student = new Student(); Lock lock = new ReentrantLock(); Condition produceCondition = lock.newCondition(); Condition consumerCondition = lock.newCondition(); ProduceTest produceTest = new ProduceTest(student, lock, produceCondition,
consumerCondition); ConsumerTest consumerTest = new ConsumerTest(student, lock, produceCondition, consumerCondition); produceTest.start(); consumerTest.start(); } } class ProduceTest extends Thread { private Student student; private Lock lock; private Condition produceCondition;
private Condition consumerCondition; public ProduceTest(Student student, Lock lock, Condition produceCondition, Condition consumerCondition) { this.student = student; this.lock = lock; this.produceCondition = produceCondition; this.consumerCondition = consumerCondition; } @Override public void run() { int num = 1; while (true) { lock.lock(); try { //如果可以生產,生產者生產 if (student.getCanProduce()) { if (num == 1) { student.setAge(6); student.setName("小王"); num = 0; } else { student.setName("老王"); student.setAge(99); num = 1; } //重置生產者不可以生產 student.setCanProduce(false); } consumerCondition.signalAll(); produceCondition.await(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } } } class ConsumerTest extends Thread { private Student student; private Lock lock; private Condition produceCondition; private Condition consumerCondition; public ConsumerTest(Student student, Lock lock, Condition produceCondition, Condition consumerCondition) { this.student = student; this.lock = lock; this.produceCondition = produceCondition; this.consumerCondition = consumerCondition; } @Override public void run() { while (true) { lock.lock(); try { //如果不可以生產,進行消費 if (!student.getCanProduce()) { //重置生產者可以生產 student.setCanProduce(true); System.out.println(student.toString()); } produceCondition.signalAll(); consumerCondition.await(); } catch (Exception e) { e.printStackTrace(); } finally { lock.unlock(); } } } } class Student { private String name; private Integer age; private Boolean canProduce = true; public Boolean getCanProduce() { return canProduce; } public void setCanProduce(Boolean canProduce) { this.canProduce = canProduce; } public String getName() { return name; } public void setName(String name) { this.name = name; } public Integer getAge() { return age; } public void setAge(Integer age) { this.age = age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age=" + age + '}'; } }

lock中常用方法:

lock()、unlock()

	Lock lock = new ReentrantLock();
	lock.lock();
	try{
	//可能會出現執行緒安全的操作
	}finally{
	//一定在finally中釋放鎖
	//也不能把獲取鎖在try中進行,因為有可能在獲取鎖的時候丟擲異常
	  lock.unlock();
	}

await()、signal()、signalAll()

	Lock lock = new ReentrantLock();
	Condition produceCondition = lock.newCondition();
	Condition consumerCondition = lock.newCondition();

	consumerCondition.signalAll();
	produceCondition.await();

lock中的await方法類似於synchronized的wait,
signal、signalAll類似於notify、notifyAll。

需要注意:
雖然多個執行緒使用同一把lock鎖,
但是每個執行緒的condition都是唯一的,
使用時需要注意。


trylock()
其功能與 lock() 一樣,不過會有返回值,
true:獲取到lock鎖;false:未獲取lock鎖。

   if (lock.tryLock()) {
        try {
            //如果不可以生產,進行消費
            if (!student.getCanProduce()) {
                //重置生產者可以生產
                student.setCanProduce(true);
                System.out.println(student.toString());
            }

            produceCondition.signalAll();
            consumerCondition.await();
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }

tryLock(long time, TimeUnit unit)
與tryLock()類似,
只不過在未獲取到鎖時,設定了一個等待時間來嘗試再次拿鎖。