吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 4253|回复: 5
收起左侧

[Java 转载] [笔记] Java多线程synchronized,wait和notify的使用

[复制链接]
阳光下的少年 发表于 2019-2-4 20:27

Java多线程synchronized,wait和notify的使用

前言

  • 这段时间再看Java多线程,后面的wait()和notify()总是不知道什么时候用或者说怎么用
  • synchronized虽然知道这个的用法,但是却不知道在哪里使用合适
  • 今天晚上看了一篇文章,然后自己分析了一下,终于搞懂了,这篇帖子分享给有和我一样问题的小伙伴.
    public class DemoNumberLimit{
    public static void main(String args[]){
        Object obj = new Object();
        Thread threadOne = new Thread(){
            public void run(){
                for (int i=0;i<50;i++){
                    System.out.println(Thread.currentThread().getName()+":"+i);
                    try{
                        Thread.sleep(500);
                    }
                    catch(InterruptedException e){
                        e.printStackTrace();
                    }
                }
                //华丽的分割线
                for(int i=0;i<50;i++)
                    System.out.print("=");
                System.out.println();       //换行
                //同步
                synchronized(obj){
                    obj.notify();
                }
                System.out.println("第一个线程接着执行");
                for(int i = 51;i<101;i++){
                    System.out.println(Thread.currentThread().getName()+":"+i);
                    try{
                        Thread.sleep(500);
                    }
                    catch(InterruptedException e){
                        e.printStackTrace();
                    }
                }
                System.out.println("线程1执行完成");
            }
        };
        //线程2
        Thread threadTwo = new Thread(){
            public void run(){
                synchronized(obj){
                    try{
                        obj.wait();
                    }
                    catch(InterruptedException e){
                        e.printStackTrace();
                    }
                    System.out.println("线程2:");
                    System.out.println("线程1的上半部分执行完成,开始执行下半部分");
                }
            }
        };
        threadOne.start();
        threadTwo.start();
        threadOne.setName("One");
        threadTwo.setName("Two");
    }
    }
  • 我在这里贴出运行结果图,帮助大家理解
    One:0
    One:1
    One:2
    One:3
    One:4
    One:5
    One:6
    One:7
    One:8
    One:9
    One:10
    One:11
    One:12
    One:13
    One:14
    One:15
    One:16
    One:17
    One:18
    One:19
    One:20
    One:21
    One:22
    One:23
    One:24
    One:25
    One:26
    One:27
    One:28
    One:29
    One:30
    One:31
    One:32
    One:33
    One:34
    One:35
    One:36
    One:37
    One:38
    One:39
    One:40
    One:41
    One:42
    One:43
    One:44
    One:45
    One:46
    One:47
    One:48
    One:49
    ==================================================
    第一个线程接着执行
    线程2:
    线程1的上半部分执行完成,开始执行下半部分
    One:51
    One:52
    One:53
    One:54
    One:55
    One:56
    One:57
    One:58
    One:59
    One:60
    One:61
    One:62
    One:63
    One:64
    One:65
    One:66
    One:67
    One:68
    One:69
    One:70
    One:71
    One:72
    One:73
    One:74
    One:75
    One:76
    One:77
    One:78
    One:79
    One:80
    One:81
    One:82
    One:83
    One:84
    One:85
    One:86
    One:87
    One:88
    One:89
    One:90
    One:91
    One:92
    One:93
    One:94
    One:95
    One:96
    One:97
    One:98
    One:99
    One:100
    线程1执行完成
  • 代码分析:
    1. 首先看看threadOne这个线程里面的synchronized从这里开始一直到threadTwo线程的大括号结束,可以看做是一整块代码块.
    2. 然后因为synchronized和下面的线程2是一个整体所以会先执行线程2里面的两条输出语句,然后在执行线程1中后面那个for循环
  • 这些仅仅是我个人理解,如有不足请留言指出.
  • 其他问题:
    1. 线程1的synchronized语句后面的输出语句第一个线程接着执行为什么跳过for循环直接执行了线程2然后在执行线程1中的for循环.
    2. 为什么要先写notify()然后在写wait()

免费评分

参与人数 1吾爱币 +1 热心值 +1 收起 理由
lin_xop + 1 + 1 新年快乐

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

唯我独宅 发表于 2019-2-4 20:58
过年了,还在努力学习。
demon_lin 发表于 2019-2-5 23:08
天使3号 发表于 2019-7-29 01:17
本帖最后由 天使3号 于 2019-7-29 01:19 编辑

1.线程1的synchronized语句后面的输出语句第一个线程接着执行为什么跳过for循环直接执行了线程2然后在执行线程1中的for循环.
恰巧!
给你看我的执行结果:
[Bash shell] 纯文本查看 复制代码
One:48
One:49
==================================================
第一个线程接着执行
One:51
线程2:
线程1的上半部分执行完成,开始执行下半部分
One:52
One:53
One:54

从threadOne的synchronized的右}结束,这时的threadOne就释放了互斥变量obj,此时threadOne和threadTwo已经随CPU分配的时间片随机并发执行了。
虽然threadTwo好像是在synchronized代码块中,但是它锁住的是obj互斥变量,在threadOne中并不需要obj也不锁住它了。就是个并发执行的随机结果。

2.为什么要先写notify()然后在写wait()
不对,从这里的执行看,是先在threadTwo中执行的obj.wait(),释放了obj这个互斥变量,等待被唤醒(notify)。
因为在threadOne中前面太多要执行的代码,又人为的让它sleep了很久,所以从结果上看obj.notify()是在obj.wait()之后才执行的。
如果先执行了nofity,那么第二个线程的wait将永远不能被唤醒!


3.我今年过年的时候就看了你这篇文章,当时懵逼不懂并发,近段时间学的,如有不对,多多指教!
一夜梦惊人 发表于 2019-7-29 15:31
我来进行彻底讲解一下。首先贴上我的运行结果关键部分。
[Asm] 纯文本查看 复制代码
==================================================
第一个线程接着执行
One:51
线程2:
线程1的上半部分执行完成,开始执行下半部分
One:52
One:53

为什么会不一样呢?
首先这个====这里毋庸置疑是正确的,必须会在49的后面,然后synchronized哪里进行notify,而threadTwo而是另一个线程,在接到notify后,wait就会失效然后继续执行。此时你看作是一整块代码这个思想是错误的,因为两个代码在语意上是同时执行。由于CPU设计的问题才会给你这种错觉,就像一个人处理事情一样,他所谓的同时执行,其实就是做一点这件事然后又去做另一件事,看起来就是两件事同时在做。换句话说就是两块代码之间选一个随机执行,这是看运气问题,然后由于线程2后续消耗的时间极短,看起来就像是处理完线程2后才又执行的线程1。

还有一个问题,为什么你觉得要先执行nofity才行呢?那是因为你被代码所误导了,两个线程几乎同时开始,而你的线程1却在不断的sleep,这导致的就是你其实先执行了,线程2的wait。我就说到这里,你可以自行修改代码进行实验。
笑海的星星 发表于 2019-7-29 18:05
线程一和二基本上同时执行,只不过线程二等待,当线程一运行notify时,两个线程同时抢执行权,然后两个线程谁先执行谁后执行就是随机的了。没有哪个是确定的。
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - LCG - LSG ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2024-11-16 12:56

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表