Java 锁

Java 锁,第1张

Java 锁

Java 锁
  • 一、Java 锁
      • 1.1、公平锁和非公平锁
      • 1.2、可重入锁(递归锁)原理
      • 1.3、自旋锁(spinlock)
      • 1.3、读写锁

一、Java 锁 1.1、公平锁和非公平锁

解释

公平锁解释:多线程情况下,按照申请锁的顺序进行获取锁,先来先得。

非公平锁解释:多线程情况下,获取锁的顺序不是按照申请锁顺序来的。高并发情况下,可能会导致优先级反转或者饥饿现象。

两者区别

公平锁是并发环境下,每个线程获取锁,查看等待队列,如果为空,或线程是等待队列的第一个,则占有锁,否则加入等待队列,按照先进先出规则队列中取到自己。

非公平锁就是上来直接占有锁,尝试失败,在采用公平锁方式。

JAVA 锁

ReentrantLock 属于非公平锁,可以通过构造函数 Booleen值指定,True 公平锁,False 非公平锁。非公平锁优点在于吞吐量比公平锁大

synchronized 也是非公平锁

1.2、可重入锁(递归锁)原理

可重入锁 最大作用是避免死锁

package com.xin;

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


public class ReenterLockDemo {

    public static void main(String[] args) {

        Phone phone = new Phone();

        System.out.println("================synchronized================");

        new Thread(() -> {
            phone.sendQQ();
        }, "t1").start();

        new Thread(() -> {
            phone.sendQQ();
        }, "t2").start();

        try { TimeUnit.SECONDS.sleep(1); } catch (InterruptedException e) { e.printStackTrace();}
        System.out.println("================ReentrantLock================");

        Thread t3 = new Thread(phone,"t3");
        Thread t4 = new Thread(phone,"t4");

        t3.start();
        t4.start();

    }

}

class Phone implements Runnable{

    public synchronized void sendQQ() {
        System.out.println(Thread.currentThread().getName() + "t invoke:sendQQ");
        sendWeChat();
    }

    public synchronized void sendWeChat() {
        System.out.println(Thread.currentThread().getName() + "t #####invoke:sendWeChat");
    }

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

    Lock lock = new ReentrantLock();
    public void get() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "t invoke:get");
            set();
        } finally {
            lock.unlock();
        }
    }

    public void set() {
        lock.lock();
        try {
            System.out.println(Thread.currentThread().getName() + "t invoke:set");
        } finally {
            lock.unlock();
        }
    }

}

1.3、自旋锁(spinlock)

理论

获取线程的锁不会被阻塞,线程会采用循环的方式获取锁,好处减少上下文切换资源浪费,缺点是循环消耗CPU。

代码

package com.xin;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicReference;


public class SpinlockDemo {


    AtomicReference atomicReference = new AtomicReference();

    public static void main(String[] args) {
        SpinlockDemo spinlockDemo = new SpinlockDemo();
        new Thread(() -> {
            spinlockDemo.myLock();
            try {
                TimeUnit.SECONDS.sleep(5);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            spinlockDemo.myUnlock();
        }, "AA").start();

        try {
            TimeUnit.SECONDS.sleep(1);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }

        new Thread(() -> {
            spinlockDemo.myLock();
            spinlockDemo.myUnlock();
        }, "BB").start();
    }

    public void myLock() {
        Thread thread = Thread.currentThread();
        System.out.println(Thread.currentThread().getName() + "come in");

        while (!atomicReference.compareAndSet(null, thread)) {

        }
    }

    public void myUnlock() {
        Thread thread = Thread.currentThread();
        atomicReference.compareAndSet(thread, null);
        System.out.println(Thread.currentThread().getName() + "invoke out");
    }

}
 

1.3、读写锁

理论

独占锁(写锁):synchronized、ReentrantLock

共享锁(读锁):

互斥锁:ReadWriteLock

代码

读写锁代码
ReentrantReadWriteLock

package com.xin;

import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.ReentrantReadWriteLock;


public class ReadWriteLockDemo {

    public static void main(String[] args) {

        MyCache myCache = new MyCache();


        for (int i = 1; i <= 5; i++) {
            final int ii = i;
            new Thread(() -> {
                myCache.set(ii + "", ii + "");
                myCache.get(ii + "");
            }, String.valueOf(i)).start();
        }

    }

}

class MyCache {

    private volatile Map map = new HashMap<>();

    ReentrantReadWriteLock reentrantReadWriteLock = new ReentrantReadWriteLock();
    
    public void get(String key) {
        reentrantReadWriteLock.readLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "t 进行读取");
            TimeUnit.MILLISECONDS.sleep(300);
            Object o = map.get(key);
            System.out.println(Thread.currentThread().getName() + "t 读取值:" + o);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            reentrantReadWriteLock.readLock().unlock();
        }
    }

    public void set(String key, Object value) {
        reentrantReadWriteLock.writeLock().lock();
        try {
            System.out.println(Thread.currentThread().getName() + "t 进行写入" + value.toString());
            TimeUnit.MILLISECONDS.sleep(300);
            map.put(key, value);
            System.out.println(Thread.currentThread().getName() + "t 写入成功");
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            reentrantReadWriteLock.writeLock().unlock();
        }
    }

}

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/zaji/5079492.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-11-16
下一篇 2022-11-16

发表评论

登录后才能评论

评论列表(0条)