记一道java多线程代码的调试过程

ppt上有一份java多线程代码, 功能: 实现两个线程交替做加法

最后debug成功的代码如下:

package MultiThread;

public class AddOnehundred implements Runnable{

    public static void main(String[] args) {
        AddOnehundred A1 = new AddOnehundred();
        //AddOnehundred A2 = new AddOnehundred();
        Thread t1 = new Thread(A1, "线程1");
        Thread t2 = new Thread(A1, "线程2");
        t1.start();
        t2.start();
    }
    private int i = 1;
    @Override
    public void run(){
        while(true) {
            synchronized(this){
                notify();//唤醒正在等待中的进程
                if(i <= 100){
                    System.out.println(Thread.currentThread().getName() + ":"+i++);
                }
                else
                    break;
                try{
                    wait();
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }   
        }
    }
}

在debug这段代码的过程中, 我遇到了如下问题:

线程死锁

                AddOnehundred A1 = new AddOnehundred();
        //AddOnehundred A2 = new AddOnehundred();
        Thread t1 = new Thread(A1, "线程1");
        Thread t2 = new Thread(A1, "线程2");
        t1.start();
        t2.start();

注意到我注释了一行语句

这里涉及到 synchronized关键字的用法

synchronized 对应的锁是对象锁
如果我实例化了两个对象, 并且分别创建了线程, 那么就有两把锁

这也就是导致死锁原因, 因为线程A的锁是无法由线程B来释放的

所以将代码修改成实例化一个对象, 并且在这个对象的基础上创建两个线程, 这样就只有一把锁, 线程之间就可以互相通信

run方法

while(true) {
            synchronized(this){
                notify();//唤醒正在等待中的进程
                if(i <= 100){
                    System.out.println(Thread.currentThread().getName() + ":"+i++);
                }
                else
                    break;
                
                try{
                    wait();
                }catch(InterruptedException e){
                    e.printStackTrace();
                }
            }

假设一个线程A进入了, A持有锁, 并且A去唤醒其他的线程(就算其他的线程被唤醒了也没事,它们还是处于阻塞状态)

之后A执行一次操作, 并且尝试调用wait方法, 释放自己持有的锁, 让其他的线程进来(这就很像管程了)

线程B已经在管程外面等待很久了, 进来之后先唤醒A, A出去了, 但是A进不来的

ok这样就能实现了

变量的问题

注意到int i = 1声明的位置

不同的位置会有不同的效果

尝试之后只有将i放在方法的外面才能达到效果

如果放在方法里面, while循环的外面, 会导致两个线程打印的值是一样的

放在while循环里面或者synchronized里面是不太可能的, 不然就无法实现加法了

最后的效果如下:


10651191-8c64b58987772a1e.png

参考

https://www.cnblogs.com/wl0000-03/p/5973039.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值