美文网首页
Java中的锁

Java中的锁

作者: 被虐的小鸡 | 来源:发表于2020-07-20 16:44 被阅读0次

    锁的种类

    1.类锁
    持有该类的字节码对象的锁

    public static synchronized void  xx(){}
    public void xx(){
        synchronized(xx.class){
    
        }
    }
    

    2.对象锁
    持有该类对象的锁,前两种持有的是XX.this,最后一种持有的是成员变量的锁

    public synchronized void xx(){}
    public void xx(){
        synchronized(this){
        }
    }
    Object obj=new Object();
    public void xx(){
        synchronized(obj){
        }
    }
    

    3.显示锁
    显示锁就是程序员在代码中可以控制加锁,释放锁的操作。类锁和对象锁都是使用synchronized关键字来加锁,他在native帮我们完成了加锁和释放锁的操作,因此synchronized也被称为内置锁。

    ReentrantLock lock=new ReentrantLock();
    public void xx(){
        lock.lock();
        xxxxxxxxx;
        lock.unlock();
    }
    

    Synchronized和ReentrantLock

    这两种锁都是重入锁,代表在递归方法中还可以继续获取锁,内部有一个计数器来计算我们获取同一个锁的次数
    这两种锁都是非公平锁
    new ReentrantLock(true);是公平锁
    非公平锁效率比较高

    public synchronized void xx(){
        xxxxxxxxxx;
        xx();
    }
    

    wait和notify

    wait和notify都必须在synchronized中使用。因为notify和wait在进行操作时都必须获取当前锁,但是当执行完wait和notify之后会释放自己持有的锁。

    public synchronized void xx(){
          xxxxxxxxxxxx;
          notify();
          wait();
    }
    

    生产者和消费者

    模拟生产和消费者去生产和消费面包

    public class Test {
        static class Container{
            private int id;
            private boolean flag;
    
            public synchronized void out(){
    
                if (flag) {
                    System.out.println("当前线程:" + Thread.currentThread().getName() + ",消费了" + this.id);
    
                    flag=false;
                    notify();
    
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
    
            public synchronized void put(){
                if (!flag) {
                    id += 1;
    
                    System.out.println("当前线程:" + Thread.currentThread().getName() + "------------------,生产了" + this.id);
    
                    flag=true;
    
                    notify();
    
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
    
        static class ProduceThread implements Runnable{
            private Container container;
    
            public ProduceThread(Container container) {
                this.container = container;
            }
    
            @Override
            public void run() {
    
                for (int i = 0; i < 20; i++) {
                    container.put();
                }
            }
        }
    
        static class ConsumerThread implements Runnable{
            private Container container;
    
            public ConsumerThread(Container container) {
                this.container = container;
            }
    
            @Override
            public void run() {
                for (int i = 0; i < 20; i++) {
                    container.out();
                }
            }
        }
    
        public static void main(String[] args) {
            Container container = new Container();
    
            new Thread(new ProduceThread(container)).start();
    
            new Thread(new ConsumerThread(container)).start();
        }
    
    }
    

    之前面试遇到过相似的题目

    有一个数组,{1,2,3,4,5,6...},使用两个线程,线程A打印奇数,线程B打印偶数
    解决方案:

    public class Demo {
        
        static class Print{
            private int i=0;
            private int[] data;
            private boolean flag;
    
            public Print(int[] data) {
                this.data = data;
            }
    
            public synchronized void printJ(){
                if (!flag){
                    System.out.println(data[i]);
                    i++;
                    flag=true;
    
                    notify();
    
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
    
            public synchronized void printO(){
                if (flag){
                    System.out.println(data[i]);
    
                    i++;
    
                    flag=false;
    
                    notify();
    
                    try {
                        wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        }
    
        static class A extends Thread{
            private Print print;
    
            public A(Print print) {
                this.print = print;
            }
    
            @Override
            public void run() {
                super.run();
                while (print.i<print.data.length){
                    print.printJ();
                }
            }
        }
    
        static class B extends Thread{
            private Print print;
    
            public B(Print print) {
                this.print = print;
            }
    
            @Override
            public void run() {
                super.run();
                while (print.i<print.data.length){
                    print.printO();
                }
            }
        }
    
    
        public static void main(String[] args) {
            Print print = new Print(new int[]{1, 2, 3, 4, 5});
            new A(print).start();
            new B(print).start();
        }
    }
    

    相关文章

      网友评论

          本文标题:Java中的锁

          本文链接:https://www.haomeiwen.com/subject/vqcykktx.html