java多线程:锁

常见的锁 Synchronized 和 Lock
线程不安全 线程安全
List CopyOnWriteList
Map ConcurrentHashMap
Set CopyOnWriteSet

从CopyonWriteList的底层看到 add方法 是添加了锁的

public boolean add(E e) {
        synchronized(this.lock) {
            Object[] es = this.getArray();
            int len = es.length;
            es = Arrays.copyOf(es, len + 1);
            es[len] = e;
            this.setArray(es);
            return true;
        }
    }

Synchronized锁

公用的变量是谁锁的就是谁,这里银行账户是公用的是银行账户,锁的就是Synchronized(账户)


public class UnsafeBank {
    public static void main(String[] args) {
        Account account = new Account(100,"结婚基金");
        Drawing you = new Drawing(account,50,"你");
        Drawing girlfriend = new Drawing(account,80,"你老婆");
        you.start();
        girlfriend.start();
    }
}
class Account {
    int money;
    String name;
    public Account(int money, String name) {
        this.money = money;
        this.name = name;
    }
}
class Drawing extends Thread {
    Account account ;
    int drawingmoney;
    int nowmoney;
    public Drawing(Account account,int drawingMoney,String name) {
        this.account = account;
        this.drawingmoney = drawingMoney;
    }

    @Override
    public void run() {
        synchronized (account) {
            if ( account.money - drawingmoney <0) {
                System.out.println(this.getName()+" money is not enough");
                return;
            }
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            account.money = account.money - drawingmoney;
            System.out.println(account.name +"余额为:" + account.money);

        }

    }
}

锁Synchronize 可以加到公共变量上面,也可以去锁某个方法
Lock锁 有三种实现,ReEntranceLock, ReadLock, WriteLock()

卖票问题——synchronize

import java.util.concurrent.TimeUnit;

public class SaleTicket_sunchronized {
    public static void main(String[] args) {
        Ticket2 ticket2 = new Ticket2();
        new Thread(()->{
            for(int i=0;i<40;i++) {
                ticket2.sales();
            }
        },"a").start();
        new Thread(()->{
            for(int i=0;i<40;i++) {
                ticket2.sales();
            }
        },"b").start();
        new Thread(()->{
            for(int i=0;i<40;i++) {
                ticket2.sales();
            }
        },"c").start();

    }
}
class Ticket2 {
    private Integer num = 100;
// 锁方法
//    public synchronized void sales() {
//        if(num > 0) {
//            System.out.println(Thread.currentThread().getName()+"剩余票数量"+num--);
//        }
//        try {
//            TimeUnit.MILLISECONDS.sleep(50);
//        } catch (InterruptedException e) {
//            e.printStackTrace();
//        }
//    }
    public void sales() {
    	// 锁代码块
        // 和 Synchronized ( Ticket.class 是一样的)
        synchronized (this) {
            if(num > 0) {
                System.out.println(Thread.currentThread().getName()+"剩余票数量"+num--);
            }
            try {
                TimeUnit.MILLISECONDS.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}


Lock锁

package com.pq.multiThread.syn;

import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
// synchronized 可以锁代码块,可以锁方法 锁代码块的时候里面的参数要保证唯一
public class SaleTicket_lock {
    public static void main(String[] args) {
        Ticket1 ticket1 = new Ticket1();
        new Thread(()->{
            for(int i=0;i<100;i++) {
                ticket1.sale();
            }
        },"a").start();
        new Thread(()->{
            for(int i=0;i<100;i++) {
                ticket1.sale();
            }
        },"b").start();
        new Thread(()->{
            for(int i=0;i<100;i++) {
                ticket1.sale();
            }
        },"c").start();
    }
}
class Ticket1 {
    private Integer count = 100;
    Lock lock = new ReentrantLock();
    public void sale() {
        lock.lock();
        try {
            if (count > 0) {
                System.out.println(Thread.currentThread().getName()+count--+"张票。。");
            }
            TimeUnit.MILLISECONDS.sleep(100);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

synchronize 和 Lock的区别

//总结二者区别
// synchronized 是内置关键字 ## Lock 是对象
//synchronized 适合少量代码块,方法 ## Lock适合锁大量代码
// 无法判断锁的状态 ## 可以判断锁的状态
// 会自动释放锁 ## 需要手动释放锁,否则会死锁
// 锁后别的线程会傻傻等待 ## Lock锁不会一直等待下去
// 可重入锁 非公平 ## 可重入锁 默认非公平(true)

生产者消费者问题

生产者消费者问题 涉及线程之间的通信问题

synchronized 主要使用wait(), notifyAll() 进行等待和唤醒


public class ConsumerAndProduct_syn {
    public static void main(String[] args) {
        Pool1 pool1 = new Pool1();
        new Thread(()->{
            for (int i=0;i<10;i++) {
                try {
                    pool1.increament1();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"a").start();
        new Thread(()->{
            for (int i=0;i<10;i++) {
                try {
                    pool1.decreament1();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"b").start();
    }
}

// 
class Pool1 {
    private int num1=1;
    public synchronized void increament1() throws InterruptedException {
        // 我设定池内数量最多为2 ,所以是和2进行比较,这个值是可以改的
        while (num1 >=2) {
            //等待 保持所持有的锁
            this.wait();
        }
        System.out.println("生产了一个 池内数量为  "+ (++num1));
        //唤醒别的线程
        this.notifyAll();

    }
    public synchronized void decreament1() throws InterruptedException {
        // 为0 的时候就不能再消费了
        while (num1 < 1) {
            this.wait();
        }
        System.out.println("消费了一个 池内数量为  "+ (--num1));
        this.notifyAll();
    }
}

JUC 的Lock方法

package com.pq.multiThread.consumer;

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

public class ConsumerAndProduct_juc {
    public static void main(String[] args) {
        Pool2 pool2 = new Pool2();

        new Thread(()->{
            for(int i=0;i<10;i++) {
                try {
                    pool2.increament2();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"B").start();
        new Thread(()->{
            for(int i=0;i<10;i++) {
                try {
                    pool2.decreament2();
                    TimeUnit.MILLISECONDS.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"C").start();
        new Thread(()->{
            for(int i=0;i<10;i++) {
                try {
                    pool2.decreament2();
                    TimeUnit.MILLISECONDS.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
        },"A").start();
    }
}

class Pool2 {
    private int num1=1;
    Lock lock = new ReentrantLock();
    Condition condition = lock.newCondition();

    public void increament2() throws InterruptedException {
        // 我设定池内数量最多为2 ,所以是和2进行比较,这个值是可以改的
        lock.lock();
        try{
            while (num1 >= 2) {
                condition.await();
            }
            System.out.println(Thread.currentThread().getName()+ "生产了一个 池内数量为  "+(++num1));
            condition.signalAll();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }


    }
    public void decreament2() throws InterruptedException {
        lock.lock();
        try{
            while (num1 < 1) {
                condition.await();
            }
            System.out.println(Thread.currentThread().getName()+ "消费了一个 池内数量为  "+(--num1));
            condition.signalAll();
        } catch (Exception e){
            e.printStackTrace();
        } finally {
            lock.unlock();
        }

    }
}


Lock并不是简单的对synchronized的方法进行了覆盖,Lock可以做到精准唤醒线程,利用的是condition.signal()

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值