自己动手写Concurrent锁工具-严格的块结构

2 篇文章 0 订阅

一、为什么1.5后会引入Concurrent包

其实应该这样说 Synchronized 有什么局限性:

  1. 不能一处加锁,另一处释放;
  2. 没有超时机制;
  3. 没有公平机制;
  4. 没有读写功能;
  5. 。。。

  • 严格的块结构
  • 活跃性问题
  • 改变锁的语义:重入性、读写保护、公平性
  • 访问控制

二、Java原生提供的锁工具有哪些

  • Synchronized
  • Object.wait()
  • Object.notify()
  • Object.notifyAll()

PS:JavaSynchronized是基于每线程而不是没调用

三、处理(不能一处加锁,另一处释放)的问题

public class Mutex {
    protected volatile boolean inuse = false;

    public void acquire() throws InterruptedException {
        if (Thread.interrupted())
            throw new InterruptedException();
        synchronized (this) {
            try {
                while (inuse)
                    wait();
                inuse = true;
            } catch (InterruptedException ex) {
                notify();
                throw ex;
            }
        }
    }

    public synchronized void release() {
        inuse = false;
        notify();
    }
}

四、实践

上述的锁支持在一处加锁,在另一处释放。是骡子是马,拉出来溜溜!

一个常见的并发编程题,两个线程交替打印奇数和偶数:

import com.google.common.base.Joiner;
import java.util.concurrent.TimeUnit;

public class TurnOutPut {
    private static int index = 1;
    private boolean isOdd = true;
    private boolean isEven = true;

    public void oddOutput(Mutex mutex) {
        while (true) {
            try {
                mutex.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (!isOdd) {
                mutex.release();
                continue;
            }
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Joiner.on("").join("【odd】", "id: ", Thread.currentThread().getId(), ", val: ", index++));
            isOdd = false;
            isEven = true;
            mutex.release();
        }
    }
    public void evenOutput(Mutex mutex) {
        while (true) {
            try {
                mutex.acquire();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if (!isEven) {
                mutex.release();
                continue;
            }
            try {
                TimeUnit.MILLISECONDS.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println(Joiner.on("").join("【even】", "id: ", Thread.currentThread().getId(), ", val: ", index++));
            isEven = false;
            isOdd = true;
            mutex.release();
        }
    }

    public static void main(String[] args) throws InterruptedException {
        final TurnOutPut turnOutPut = new TurnOutPut();
        final Mutex mutex = new Mutex();
        new Thread(new Runnable() {
            public void run() {
                turnOutPut.oddOutput(mutex);
            }
        }).start();
        new Thread(new Runnable() {
            public void run() {
                turnOutPut.evenOutput(mutex);
            }
        }).start();

        Thread.currentThread().join();
    }
}

五、分析&问题

Mutex类volatile关键字不需要可以吗?

synchronized、wait、notify之间的关系是怎样的?

synchronized到底在同步什么?

wait在等待什么?

notify在通知什么?

        Mutex是不完备的,如果恶意的线程直接调用release怎么办?


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值