synchronized和ReentrantLock区别

sychronized

在java中,每一个对象有且仅有一个同步锁。这也意味着,同步锁是依赖于对象而存在。
当我们调用某对象的synchronized方法时,就获取了该对象的同步锁。例如,synchronized(obj)就获取了“obj这个对象”的同步锁。
不同线程对同步锁的访问是互斥的。也就是说,某时间点,对象的同步锁只能被一个线程获取到!通过同步锁,我们就能在多线程中,实现对“对象/方法”的互斥访问。 例如,现在有两个线程A和线程B,它们都会访问“对象obj的同步锁”。假设,在某一时刻,线程A获取到“obj的同步锁”并在执行一些操作;而此时,线程B也企图获取“obj的同步锁” —— 线程B会获取失败,它必须等待,直到线程A释放了“该对象的同步锁”之后线程B才能获取到“obj的同步锁”从而才可以运行。

sychronized有三条原则:
1. 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的该“synchronized方法”或者“synchronized代码块”的访问将被阻塞。
2. 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程仍然可以访问“该对象”的非同步代码块。
3. 当一个线程访问“某对象”的“synchronized方法”或者“synchronized代码块”时,其他线程对“该对象”的其他的“synchronized方法”或者“synchronized代码块”的访问将被阻塞。

synchronized会在进入同步块的前后分别形成monitorenter和monitorexit字节码指令.在执行monitorenter指令时会尝试获取对象的锁,如果此没对象没有被锁,或者此对象已经被当前线程锁住,那么锁的计数器加一,每当monitorexit被锁的对象的计数器减一.直到为0就释放该对象的锁.由此synchronized是可重入的,不会出现自己把自己锁死.

ReentrantLock

ReentrantLock是一个可重入的互斥锁,又被称为“独占锁”

顾名思义,ReentrantLock锁在同一个时间点只能被一个线程锁持有;而可重入的意思是,ReentrantLock锁,可以被单个线程多次获取。
ReentrantLock分为 公平锁非公平锁 。它们的区别体现在获取锁的机制上是否公平。 是为了保护竞争资源,防止多个线程同时操作线程而出错,ReentrantLock在同一个时间点只能被一个线程获取(当某线程获取到“锁”时,其它线程就必须等待);ReentraantLock是通过一个FIFO的等待队列来管理获取该锁所有线程的。在“公平锁”的机制下,线程依次排队获取锁;而“非公平锁”在锁是可获取状态时,不管自己是不是在队列的开头都会获取锁。
以对象的方式来操作对象锁,相对于sychronized需要在finally中去释放锁。

synchronized和ReentrantLock的区别

除了synchronized的功能,多了三个高级功能。
等待可中断,公平锁,绑定多个Condition。
1. 等待可中断:在持有锁的线程长时间不释放锁的时候,等待的线程可以选择放弃等待,tryLock(long timeout, TimeUnit unit)
2. 公平锁:按照申请锁的顺序来一次获得锁称为公平锁,synchronized的是非公平锁,ReentrantLock可以通过构造函数实现公平锁。new RenentrantLock(boolean fair)
3. 绑定多个Condition:通过多次newCondition可以获得多个Condition对象,可以简单的实现比较负责的线程同步的功能,通过await(),signal();

实现消费者模式

sychronized

 public static class Depot {
        private int mCapacity;
        private int mSize;

        public Depot(int capacity) {

            mCapacity = capacity;
            mSize = 0;
        }


        public synchronized void produce(int val) {
            try {
                int left = val;
                while (left > 0) {
                    while (mSize >= mCapacity)
                        wait();

                    int inc = (mSize + left) > mCapacity ? (mCapacity - mSize) : left;
                    mSize += inc;
                    left -= inc;

                    System.out.println("produce  Thread: " + Thread.currentThread().getName() + " val: " + val + " mSize: " + mSize + " left: " + left);

                    notifyAll();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }

        public synchronized void consume(int val) {
            try {
                int left = val;
                while (left > 0) {
                    while (mSize <= 0)
                        wait();
                    int inc = (mSize - left) < 0 ? mSize : left;
                    mSize -= inc;
                    left -= inc;
                    System.out.println("consume  Thread: " + Thread.currentThread().getName() + " val: " + val + " mSize: " + mSize + " left: " + left);
                    notifyAll();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

    private static class Producer {
        private Depot depot;

        public Producer(Depot depot) {
            this.depot = depot;
        }

        public void produce(int val) {
            new Thread() {
                @Override
                public void run() {
                    depot.produce(val);
                }
            }.start();
        }
    }



    static class Customer {
        private Depot depot;

        public Customer(Depot depot) {
            this.depot = depot;
        }

        public void consume(int val) {
            new Thread() {
                @Override
                public void run() {
                    depot.consume(val);
                }
            }.start();
        }
    }


    public static void main(String[] args) {
        Depot depot = new Depot(100);
        Producer producer = new Producer(depot);
        Customer customer = new Customer(depot);

        producer.produce(60);
        producer.produce(120);
        customer.consume(90);
        customer.consume(150);
        producer.produce(110);
    }

ReentrantLock

public static class Depot {
        private int mCapacity;
        private int mSize;
        private Lock mLock;
        private Condition mFullCondition;
        private Condition mEmptyCondition;

        public Depot(int capacity) {
            mCapacity = capacity;
            mSize = 0;
            mLock = new ReentrantLock();
            mFullCondition = mLock.newCondition();
            mEmptyCondition = mLock.newCondition();
        }


        public void produce(int val) {
            mLock.lock();
            try {
                int left = val;
                while (left > 0) {
                    while (mSize >= mCapacity)
                        mFullCondition.await();

                    int inc = (mSize + left) > mCapacity ? (mCapacity - mSize) : left;
                    mSize += inc;
                    left -= inc;

                    System.out.println("produce  Thread: " + Thread.currentThread().getName() + " mSize: " + mSize + " left: " + left);

                    mEmptyCondition.signal();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                mLock.unlock();
            }
        }

        public void consume(int val) {
            mLock.lock();

            try {
                int left = val;
                while (left > 0) {
                    while (mSize <= 0)
                        mEmptyCondition.await();
                    int inc = (mSize - left) < 0 ? mSize : left;
                    mSize -= inc;
                    left -= inc;
                    System.out.println("consume  Thread: " + Thread.currentThread().getName() + " mSize: " + mSize + " left: " + left);
                    mFullCondition.signal();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            } finally {
                mLock.unlock();
            }
        }
    }

    static class Producer {
        private Depot depot;

        public Producer(Depot depot) {
            this.depot = depot;
        }

        public void produce(int val) {
            new Thread() {
                @Override
                public void run() {
                    depot.produce(val);
                }
            }.start();
        }
    }

    static class Customer {
        private Depot depot;

        public Customer(Depot depot) {
            this.depot = depot;
        }

        public void consume(int val) {
            new Thread() {
                @Override
                public void run() {
                    depot.consume(val);
                }
            }.start();
        }
    }


    public static void main(String[] args) {
        Depot depot = new Depot(100);
        Producer producer = new Producer(depot);
        Customer customer = new Customer(depot);

        producer.produce(60);
        producer.produce(120);
        customer.consume(90);
        customer.consume(150);
        producer.produce(110);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值