乐观锁与悲观锁

悲观锁

悲观锁是指在用读取锁锁定一块代码的时候,另一个读取锁依然可以进入该代码块,而写锁不可以进入.在用写锁锁定一段代码的时候,读锁和写锁都不能进入该代码块.

乐观锁

乐观锁其实就是写锁优先机制,读锁在锁定某一代码块的时候,如果没有写锁竞争,那么就会获得该锁的权限,如果进行锁定的时候发现有写锁正在竞争,那么就会抛出例外,需要重新操作进行锁定.竞争标志则是
long stamp = lock.tryOptimisticRead();//有竞争返回0
lock.validate(stamp);//有竞争返回true

悲观锁示例

package Test;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class Main {
    public static void main(String[] args) {
        Pessimistic p = new Pessimistic();
        Thread t1=new Thread(()->{
            p.addSome();
        });
        Thread t2=new Thread(()->{
            p.getSome();
        });

        Thread t3=new Thread(()->{
            p.getSome();
        });

        t1.start();
        t2.start();
        t3.start();


    }

}


class Pessimistic{
    private ReadWriteLock lock = new ReentrantReadWriteLock();

    public void addSome() {
        lock.writeLock().lock();

        try {
            System.out.println("addSome方法被我锁啦,我要霸占这把锁2s钟");
            Thread.sleep(2000);
        }catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }finally {
            lock.writeLock().unlock();
        }
    }


    public void getSome() {
        lock.readLock().lock();

        try {
            System.out.println("getSome方法被我锁啦,我要霸占这把锁2s钟");
            Thread.sleep(2000);
        }catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }finally {
            lock.readLock().unlock();
        }
    }
}

/*-------------------------------------
结果:

addSome方法被我锁啦,我要霸占这把锁2s钟
//间隔两秒
getSome方法被我锁啦,我要霸占这把锁2s钟
getSome方法被我锁啦,我要霸占这把锁2s钟

情况2:
getSome方法被我锁啦,我要霸占这把锁2s钟
getSome方法被我锁啦,我要霸占这把锁2s钟
//间隔两秒
addSome方法被我锁啦,我要霸占这把锁2s钟
------------------------------------*/

乐观锁示例

package Test;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;
import java.util.concurrent.locks.StampedLock;

public class Main {
    public static void main(String[] args) {
        Optimistic p = new Optimistic();
        Thread t1=new Thread(()->{
            p.addSome();
        });
        Thread t2=new Thread(()->{
            p.getSome();
        });

        Thread t3=new Thread(()->{
            p.getSome();
        });

        t1.start();
        t2.start();
        t3.start();


    }

}


class Pessimistic{
    private ReadWriteLock lock = new ReentrantReadWriteLock();

    public void addSome() {
        lock.writeLock().lock();

        try {
            System.out.println("addSome方法被我锁啦,我要霸占这把锁2s钟");
            Thread.sleep(2000);
        }catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }finally {
            lock.writeLock().unlock();
        }
    }


    public void getSome() {
        lock.readLock().lock();

        try {
            System.out.println("getSome方法被我锁啦,我要霸占这把锁2s钟");
            Thread.sleep(2000);
        }catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }finally {
            lock.readLock().unlock();
        }
    }
}


class Optimistic{
    private StampedLock lock =new StampedLock();
    public void addSome() {
        long stamp=lock.writeLock();
        try {
            System.out.println("addSome方法被我锁啦,我要霸占这把锁2s钟");
            Thread.sleep(2000);
        }catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }finally {
            lock.unlockWrite(stamp);
        }
    }


    public void getSome() {
        long stamp = lock.tryOptimisticRead();//如果有其他锁,戳记会为0
        try {
            if(!lock.validate(stamp)) {
                stamp=lock.readLock();
                System.out.println("getSome方法被我锁啦,我要霸占这把锁2s钟");
                Thread.sleep(2000); 
            }
        }catch (Exception e) {
            // TODO: handle exception
            e.printStackTrace();
        }finally {
            try {

                lock.unlockRead(stamp);
            }catch (Exception e) {
                // TODO: handle exception
                System.out.println("已经被write锁锁了");
            }
        }
    }
}


/*------------------------------------
结果
情况1://大多数情况
addSome方法被我锁啦,我要霸占这把锁2s钟
//间隔两秒钟
getSome方法被我锁啦,我要霸占这把锁2s钟
getSome方法被我锁啦,我要霸占这把锁2s钟


情况2:
已经被write锁锁了
addSome方法被我锁啦,我要霸占这把锁2s钟
getSome方法被我锁啦,我要霸占这把锁2s钟
------------------------------------*/

参考