同步

  • 多个线程操作同一个对象 叫同步
  • 同一个对象被多个线程同时操作 叫–并发
  • 多个线程需要等待,等待机制就是线程同步,线程同步是一种等待机制,线程都进入这个对象的等待池形成队列,等待前一个线程使用完毕
  • 不仅需要队列还需要保证线程同步的安全性
  • 在这里插入图片描述

银行取钱

public class Unsafe {
    public static void main(String[] args) {
        Account account=new Account("银行卡",100);
        YinHang hus=new YinHang(account,50,"hus");
       YinHang wife=new YinHang(account,100,"wife");
       hus.start(); wife.start();
    }
}
class Account{
    public Account(String name, int money) {
        this.name = name;
        this.money = money;
    }
    String name;
    int money;
}
class YinHang extends Thread
{
    public YinHang(Account account,int takeMoney,String name) {
        this.account = account;
        this.takeMoney = takeMoney;
        this.name=name;
    }
   String name;
    Account account;
    int takeMoney;
    int nowMoney=0;
    @Override
    public void run() {
       if(account.money<takeMoney)
       {
           System.out.println("卡里钱不够了");
           return;
       }
        try {
            Thread.sleep(1000);//等待确保两个线程都进入
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        account.money-=takeMoney;
       nowMoney+=takeMoney;
        System.out.println(name+"取走了"+takeMoney);
        System.out.println("卡里剩余"+account.money);
    }
}

在这里插入图片描述
当两个线程同时操作同一个对象Account的时候就会发生线程安全问题
两个人都以为现在还有100万

集合

list线程不同步
如果某个线程类的run方法是向list中添加一个东西
我们创建10000个这个线程类的对象 正常list中的长度就应该是10000现在却比10000少
说明有两个线程一瞬间同时操作list把数字添加到链表底层数组的同一个位置

public static void main()
{
 List<String> list=new ArrayList<>();
 for(int i=0;i<10000;i++)
 {
  new Thread(()->{
   list.add(Thread.currentThread.getName());
}).start();
}
sout(list.size());
}

线程安全 同步代码块

   for (int i = 0; i < 10000; i++) {
            new Thread(()->{
                synchronized (list){
                list.add(Thread.currentThread().getName());}
            }).start();
        }

在这里插入图片描述
在这里插入图片描述

  • 如果要同步的是同步方法锁的就是本类对象 比如买票的例子 是sellTicket()这方法在进行同步
    那就不用设置同步监听对象,因为同步方法的同步监听对象就是这个类对象本身或者反射的class对象本身
 @Override
    public void run() {
        while (flag) {
         sell();
        }
    }
    public synchronized  void sell()
    {
        if(tickets<=0)
        {
            flag=false;
            System.out.println("票已经卖完");
            return;
        }
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(Thread.currentThread().getName()+"拿到票"+tickets--);
    }
  • 如果用同步代码块就是可以锁任何类型的对象
    synchronized默认锁的对象是当前方法所在类的类对象this
    如果本类this对象并不是真正被操作的对象(真正锁的对象(同步监视对象)是被CRUD的,是变化的量),想要改变同步监视对象 就用锁同步代码块 ()括号里写同步监视对象{}里写我们用这个锁对象进行的操作

  • 对银行取钱代码改进,现在如果直接在run加sychronized发现没有改变 因为本类对象银行并不是被操作的对象
    Account账户才是被多个线程共同操作的对象 才是变化的所以我们要用同步代码块来改进

 @Override
        public void run() {
            synchronized (account)
            {
            if(account.money<takeMoney)
        {
            System.out.println("卡里钱不够了");
            return;
        }
        try {
            Thread.sleep(1000);//等待确保两个线程都进入
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        account.money-=takeMoney;
        nowMoney+=takeMoney;
        System.out.println(name+"取走了"+takeMoney);
        System.out.println("卡里剩余"+account.money);
    }
    }

死锁

互斥条件
不剥夺条件
请求保持
循环等待

Lock锁

sychronized是隐式锁 锁的对象定义麻烦 也看不到锁对象开始和结束
在这里插入图片描述
可重入锁
在这里插入图片描述

 int tickets=10;
    private ReentrantLock lock=new ReentrantLock();
    @Override
    public void run() {
        while(true) {
            try {//显示枷锁
                lock.lock();
                if (tickets <= 0) {
                    System.out.println("票卖完了");
                    return;
                }
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName() + "取到票" + tickets--);
            }finally {
                lock.unlock();//显示解锁
            }
        }
    }

在这里插入图片描述

线程通信

每一个线程都有一个锁
Object类的方法有toString() equals() hashCode()
还有wait() notify()
生产者和消费者共享同一片资源,互相依赖互为条件

  • 生产者生成产品之前,生产者会通知消费者等待,生成之后放入池子,
    池子如果满了通知消费者来消费,生产者等待
  • 消费者来池子里消费了,告诉生产者我消费完了,你可以继续生产,
    消费完池子空了,要通知生产者生产,消费者等待
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值