JAVA入门—————线程同步 AND 线程死锁

线程同步

  • 概念:由于同一进程的多个线程共享一块储存区域 在他们同时操作一个对象时 需要线程同步
  • 线程同步是一种等待机制 多个需要操作一个对象的线程进入对象的等待池 等待前面的线程使用完毕 下一个线程在使用 eg:排队买单
被操作的对象必须定义成静态成员变量 才能被所有线程共享

线程同步的优点:解决了多线程的安全问题
线程同步的缺点:当有多个线程时 每个线程都回去判断同步上的锁 降低了程序的运行效率

同步锁

  • 在线程访问对象时 加入锁机制 synchronized————当一个线程获得锁 它独占资源 其他线程必须等待 当它解锁后 其他线程才能执行
public synchronized void method(int args){} ——同步方法
  • 若将一个代码较多的方法声明为同步方法————锁的太多 浪费资源 影响效率
synchronized(对象){ 需要同步的代码; } ———同步块 同步监视器

线程进入同步方法或者同步块时 会自动获取锁 在执行完代码退出时会自动释放该锁
只有一个线程会获得该锁——————互斥锁

public class SellTicket implements Runnable{
    private static int ticket = 100;
    @Override
    public void run() {
        while(ticket>0){
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
             //sell();
            synchronized ("") {
                if (ticket <= 0) {
                    return;
                }
                System.out.println(Thread.currentThread().getName() + "卖了一张票  还剩" + (--ticket) + "张");
            }
        }
    }
//    public synchronized void sell() {  //  买票的同步方法
//        if(ticket<=0){
//            return ;
//        }
//        System.out.println(Thread.currentThread().getName()+"卖了一张票  还剩"+ (--ticket) +"张");
//    }
    public static void main(String[] args) {
        SellTicket sellTicket = new SellTicket();
        Thread thread = new Thread(sellTicket,"售票员1");
        Thread thread1 = new Thread(sellTicket, "售票员2");
        Thread thread2 = new Thread(sellTicket, "售票员3");
        thread.start();
        thread1.start();
        thread2.start();
    }
}
Lock锁 充当 同步锁
  • 锁提供了对共享资源的独占访问 每次只能有一个线程对Lock对象加锁
  • 线程开始访问共享资源之前应先获得Lock锁

synchronized与Lock的区别

Lock:

  1. 显式锁——需要手动开启和关闭
  2. 只有代码块锁
  3. 性能更好 具有更好的扩展性

Synchronized:

  1. 隐式锁——出了作用域自动释放
  2. 有代码块锁和方法锁

推荐:Lock > 同步代码块 > 同步方法

线程死锁

  • 当多个线程在执行过程中,需要等待其他线程释放资源才能运行 导致多个线程互相等待对象释放资源的情况————死锁
  • 死锁发生的条件
  1. 互斥条件:一个资源每次只能被一个进程使用
  2. 请求与保持条件:一个进程因为请求资源而等待时 对方获得的资源不释放
  3. 不剥夺条件:进程已获得的资源 在没有执行完之前 其他进程不能剥夺
  4. 循环等待条件:多个进程形成一种头尾相接的循环等待资源的关系
    只要破坏其中一个死锁条件 就能避免死锁的发生
public class ThreadLock {
    public static void main(String[] args) {
        DeadLockA deadLockA = new DeadLockA();
        Thread thread1 = new Thread(deadLockA, "线程1");
        DeadLockB deadLockB = new DeadLockB();
        Thread thread2 = new Thread(deadLockB, "线程2");
        thread1.start();
        thread2.start();
    }
}
class DeadLockA implements Runnable {

        @Override
        public void run() {
            synchronized ("A") {
                System.out.println("线程1获得了A锁");
            }
            synchronized ("B") {
                System.out.println("线程1获得了A锁和B锁");
            }
        }
    }
class DeadLockB implements Runnable{

    @Override
    public void run() {
        synchronized("B"){
            System.out.println("线程2获得了B锁");
        }
        synchronized ("A"){
            System.out.println("线程2获得了B锁和A锁");
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值