线程锁

锁是在多线程中对公共资源的控制。(java.util.concurrent.locks
locks包下的接口:

|---AbstractOwnableSynchronizer
|---AbstractQueuedLongSynchronizer
|---AbstractQueuedSynchronizer
|---Condition
|---Lock
|---LockSupport
|---ReadWriteLock
|---ReentrantLock
|---ReentrantReadWriteLock

乐观锁和悲观锁

乐观锁: 乐观锁会认为每次查询都不会造成更新丢失,所以每次都不会加锁,利用版本控制实现。
悲观锁: 该锁认为每次操作都会对数据造成更新丢失,每次查询时加上排它锁。

锁的类型

  • 可重入锁
    同一个线程中,外层函数获得锁,内层依然有该锁的代码,不受影响。
public class Hello implements Runnable{
    ReentrantLock lock = new ReentrantLock();

    private void worker(){
        lock.lock();
        System.out.println("I'm worker: " + Thread.currentThread().getId());
        sayHello();
        lock.unlock();
    }
    private void sayHello(){
        lock.lock();
        System.out.println("Hello Word");
        lock.unlock();
    }

    @Override
    public void run() {
        worker();
    }

    public static void main(String[] args) {
        Hello hello = new Hello();
        new Thread(hello).start();
        new Thread(hello).start();
        new Thread(hello).start();
    }
}
  • 自旋锁
    同一个线程两次调用lock(),会导致第二次调用lock()位置进行自旋,产生死锁。(不可重入锁)
public class SpinLock {
    private AtomicReference cas = new AtomicReference();
    public void lock() {
        Thread current = Thread.currentThread();
        // 利用CAS
        while (!cas.compareAndSet(null, current)) {
            // DO nothing
        }
    }
    public void unlock() {
        Thread current = Thread.currentThread();
        cas.compareAndSet(current, null);
    }

}
  • 可中断锁
    在等待获取锁的过程中可中断公平锁
public class Hello implements Runnable{
    ReentrantLock lock = new ReentrantLock();

    @Override
    public void run() {
        try {
            lock.lockInterruptibly();
            System.out.println("Hello Word");
            Thread.sleep(2000);
            lock.unlock();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        //正常
        Hello hello = new Hello();
        Thread t1 = new Thread(hello);
        t1.start();
        try {
            Thread.sleep(3000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        t1.interrupt();

//        InterruptedException异常
//        Hello hello = new Hello();
//        Thread t1 = new Thread(hello);
//        t1.start();
//        t1.interrupt();
    }
}
  • 公平锁
    按等待获取锁的线程的等待时间进行获取,等待时间长的优先获取。(ReentrantLock默认是公平锁
    非公平锁
public class Hello implements Runnable{
    //非公平锁
    ReentrantLock lock = new ReentrantLock(false);

    @Override
    public void run() {
        try {
            lock.lock();
            System.out.println("Hello Word" + Thread.currentThread().getName());
            Thread.sleep(2000);
            lock.unlock();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        Hello hello = new Hello();
        Thread t1 = new Thread(hello);
        t1.setName("t1");
        t1.start();

        Thread t2 = new Thread(hello);
        t2.setName("t2");
        t2.start();

        Thread t3 = new Thread(hello);
        t3.setName("t3");
        t3.start();

    }
}    
  • 读写锁
    对资源的读写的时候拆成两个部分处理。读的时候可以多线程一起读,写的时候必须同步写。
public class Hello {
    ReentrantReadWriteLock lock = new ReentrantReadWriteLock();

    public static void main(String[] args) {
        Hello hello = new Hello();
        for (int i = 0; i < 3; i++) {
            new Thread(() ->{
                try {
//                    hello.read();
                    hello.put("Hello");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }).start();
        }

    }

    public void put(Object object) throws InterruptedException {
        lock.writeLock().lock();
        System.out.println("我来写东西了++++");
        Thread.sleep(2000);
        System.out.println(Thread.currentThread().getName() + " write " + object);
        lock.writeLock().unlock();
    }

    public void read() throws InterruptedException {
        lock.readLock().lock();
        System.out.println("我来读东西了++++");
        Thread.sleep(2000);
        System.out.println(Thread.currentThread().getName() + " ++++++++++++");
        lock.readLock().unlock();
    }
}

偏向锁、轻量级锁、重量级锁

偏向锁: 它会偏向于第一个访问锁的线程,如果运行过程中,同步锁只有一个线程访问,不存在多线程竞争情况,线程不需要触发同步锁,系统会给线程加个偏向锁。
轻量级锁: 当有第二条线程加入竞争时,系统会把偏向锁升级为轻量锁。
重量级锁: 内置在java中被抽向为监视器锁(monitor)。调用成本非常高,包括系统调用引起的内核态与用户切换、线程阻塞造成的线程切换等。(Syschronized

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章