2021-07-22 线程和锁

线程

  • start() : 启动线程的唯一方式

  • setName() : 设置线程的名字 默认是Thread-0,Thread-1…

  • getName() : 获取线程的名字

  • setPriority() : 设置线程优先级

  • getPriority() : 获取线程优先级

  • static currentThread() : 获取当前线程的内存地址

  • static sleep() : 睡眠当前线程,参数是睡眠的毫秒数

  • 静态的,和用哪个对象没关系,写在哪个线程中,就获取哪个线程对象,就睡眠哪个线程

  • stop已经过时,不推荐使用,因为可能会导致死锁

  • 使用占位符的方式终止线程

  • join():合并 让当前线程等待指定线程执行完后再执行

  • yield() : 暂停当前线程,让位给其他等待中的线程执行

  • 是个静态方法,使用Thread.yield() 进行调用

  • 同优先级让位,不同优先级不让位

  • 当多个线程有可能操作同一个数据的时候,

 public static void main(String[] args) {
        Thread t1 = new Processer();
        Thread t2 = new Processer();
        t1.setName("t1");
        t2.setName("t2");
        // 设置优先级为1
        t1.setPriority(1);
        // 设置优先级为10
        t2.setPriority(10);
        t1.start();
        t2.start();
        for (int i = 0; i < 10; i++) {
            System.out.println(Thread.currentThread().getName() + " --> " + i);
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
  public static void main(String[] args) {
        Processer_02 p = new Processer_02();
        Thread t1 = new Thread(p);
        t1.setName("t1");
        t1.start();
        // t1线程是死循环,5秒后,终止它
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        // stop已经过时,不推荐使用,因为可能会导致死锁
        // t1.stop();
        // 使用占位符的方式终止线程
        p.flag = false;
    }
  public static void main(String[] args) {
        Thread t1 = new Thread(new Processor_04());
        t1.start();
        for (int i = 0; i < 10; i++) {
            // 让出当前执行的时间片,让其他等待的线程执行
            Thread.yield();
            System.out.println(Thread.currentThread().getName()+" : "+i);
        }
    }

  • 为了考虑数据的一致性和安全性,需要进行同步机制,

  • 尤其是更改操作,查询无所谓,因为查询不会对数据发生更改

  • 1 Lock 是显式锁,需要手动开启和手动关闭,而synchronized是隐式锁,除了作用域,自动解锁

  • 2 Lock 只有代码块锁,而synchronized可以代码块锁,可以方法锁

*3 使用Lock还有更多功能扩展

  • 死锁 : 就是大家在执行过程中,都遇到了对方进入加锁的方法,从而导致都访问不了的状态
    1 ) 某个线程执行完成 , 需要 先后 嵌套 锁定两个对象,在这个过程中,该线程先锁定了第一个对象
    2 ) 另一个线程执行完成 , 需要 先后 嵌套 锁定两个对象,在这个过程中,该线程先锁定了第二个对象
    3 ) 第一个线程执行中,执行到锁第二个对象的时候,发现第二个对象被第二个线程锁住了,只能等待
    4 ) 第二个线程执行中,执行到锁第一个对象的时候,发现第一个对象被第一个线程锁住了,只能等待

  • wait : 让当前线程进入挂起状态,并且会释放持有的锁 当被唤醒之后,进入就绪状态,当进入执行状态时,接着挂起的地方继续执行

  • wait() : 无参 不会自己醒,等待被唤醒 , 有参(毫秒数) 到点之后自己醒

  • notify : 随机唤醒一个在该对象中等待的线程

  • notifyAll : 唤醒在该对象中等待的所有线程

  • 三个方法必须用在加锁的方法中

  • 生产者和消费者

//synchronized锁

  public void withDraw(double money) {
        System.out.println("不需要同步的其他功能");
        // 下面代码 需要同步执行
        synchronized (this) {
            // try {
            // Thread.sleep(5000);
            // } catch (InterruptedException e) {
            // e.printStackTrace();
            // }
            double after = balance - money;
            balance = after;
            System.out.println(Thread.currentThread().getName()
                    + " --> 取款成功 : 1000.0 , 余额为 : " + balance);
        }
    }
   //lock锁
 public void withDraw(double money) {
        System.out.println("不需要同步的其他功能");
        // 加锁
        lock.lock();
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        double after = balance - money;
        balance = after;
        System.out.println(Thread.currentThread().getName()
                + " --> 取款成功 : 1000.0 , 余额为 : " + balance);

        // 解锁
        lock.unlock();
    }
//死锁

public void run() {
        // 当我们使用代码块锁,锁住o1的时候,那么 o1对象中的所有代码块锁和所有加锁的成员方法,全部锁定
        synchronized (o1) {
            // 加睡眠 是为了 让t2线程先锁住o2 , 保证一定死锁
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // System.out.println("T1已经对o1加锁");
            synchronized (o2) {
                System.out.println("T1已经对o2加锁");
            }
        }
        System.out.println("T1执行完成,o1和o2解锁");
    }
    
   public void run() {
        synchronized (o2) {
            try {
                Thread.sleep(10);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            // System.out.println("T2已经对o2加锁");
            synchronized (o1) {
                System.out.println("T2已经对o1加锁");
            }
        }
        System.out.println("T2执行完成,o1和o2解锁");
    }
多线程下安全的单例模式

    private SingLeton_01() {

    }

    // 防止指令重排
    private volatile static SingLeton_01 s = null;

    public  static SingLeton_01 getInstance() {
        if (s == null) {
            // 类锁,类中所有加锁的静态方法和语句块锁 全部锁定
            synchronized(SingLeton_01.class){
                // 双重校验
                if ( s == null) {
                    s = new SingLeton_01();
                }
            }

        }
        return s;
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值