再谈关于 java 线程,synchronized,wait,notify 的问题

<★cnmm22 动感原创:http://blog.csdn.net/cnmm22/article/details/44758269>

在我的上一篇博客里<http://blog.csdn.net/cnmm22/article/details/44273843>,我谈到了java 的线程,和线程同步的问题,但是我想了一下,可能并没有把有些事情说清楚。

既然没说清楚,所以我再谈谈。

首先,synchronized 只有一个作用,就是保证其中的代码块不被打断。

那说了,有synchronized 就行了,为啥要在后面加个小尾巴?synchronized(对象锁)?这个笔对象锁又是拿来干嘛呢?

要解释这个问题不能单靠理论,而网上所有的关于这个问题都会把重点放到理论上。我现在要把你的重点引到实际应用中去,要站到设计者的角度来考虑这个问题,

假设一个程序,无须多线程,那自然是从上到下的顺序执行。

而所有用到 synchronized  的地方,必然是有多个线程,程序不再像单线程那样简单。

这就引来一个实际的问题:synchronized 会降低程序执行效率,因为,为了保证其中的代码块被完整的执行,其他的线程可能必须要等待。

那设计者自然要想了:为了保证 synchronized 的代码块完整执行,是大家都等呢,还是只是一些相关程序等呢?

问题中已经包含了答案。

那说了,怎样判断哪些程序是相关的呢?对象锁。

至于这个问题:为啥有 wait,notify 的地方必须有synchronized?

因为必须有线程跟这些 wait 的线程拥有同样的线程锁来唤醒他们,这句话可能很难理解,但你找找你会发现:有wait的程序,一个线程往往会被创建多个实例,就比如我上一讲里的代码1,他们很显然能够拥有相同对象锁;或者必须有多个线程拥有同一个对象锁,就比如我上一讲里的代码2。

嘿,你说奇怪了,其实一点都不奇怪,很好理解,我可以明确告诉你,不可能有一个单线程程序里有 wait 这类代码的出现,因为要是真这样,线程一但wait ,再也没人叫醒他了,绝不可能有这样的程序出现。

我举个例,假设你要在一个游戏写一个暂停游戏,这必须用到 wait,同时,你必须用一个跟他持有相同对象锁的线程唤醒它。那个线程通常一个按键监听线程,你必须要证明一件事才能相信我说的,那就是游戏的主线程和按键监听线程不是同一个线程,但是可以是一组相关线程(这个很简单,只要有相同的对象锁就可以)。

你可以去试一试,在java 里,按键是有是一个专门线程,通常是 AWT-EventQueue-0 这样的后台线程,而你写的代码是在另一个线程里运行。

所以,实际当你的游戏暂停时,不是所有所有都暂停了,这也等于解释了一个线程 wait的时候,必然有其他的线程醒着,来在合适的时候叫醒哪些 wait 的线程。

时间: 2024-08-13 16:30:04

再谈关于 java 线程,synchronized,wait,notify 的问题的相关文章

Java线程 synchronized、Lock、Condition

java.util.concurrent.lock 中的Lock 框架是锁定的一个抽象,它允许把锁定的实现作为 Java 类,而不是作为语言的特性来实现.这就为Lock 的多种实现留下了空间,各种实现可能有不同的调度算法.性能特性或者锁定语义. ReentrantLock 类实现了Lock ,它拥有与synchronized 相同的并发性和内存语义,但是添加了类似锁投票.定时锁等候和可中断锁等候的一些特性.此外,它还提供了在激烈争用情况下更佳的性能.(换句话说,当许多线程都想访问共享资源时,JV

Java线程的wait(), notify()和notifyAll()

wait(), notify()和notifyAll()方法用于在线程间建立关联. 在对象上调用wait()将使线程进入WAITTING状态, 直到其他线程对同一个对象调用notify()或notifyAll(). 在任何线程上, 对一个对象调用wait(), notify()和notifyAll(), 都需要先获得这个对象的锁, 就是说, 这些方法必须在synchronized方法或代码块中调用. notify() 调用notify()时, 在所有WAITING状态的线程中只会有一个线程被通知

再谈用java实现Smtp发送邮件之Socket编程

很多其它内容欢迎訪问个人站点   http://icodeyou.com 前几天利用Socket实现了用java语言搭建webserver,全程下来应该会对Socket这个东西已经使用的很熟悉了.尽管抽象,可是使用过一次之后就会感受到它在网络通信上的作用是多么的强大.正好,今天就继续用Socket来练习使用下面Smtp协议发送一封简单的电子邮件.今天的故事呢,是我要约我女神出去吃饭啦啦啦~~~所以,面对Smtp.仅仅许成功,不许失败. 全局假定我的邮箱为[email protected]   女

Java线程与多线程教程

本文由 ImportNew - liken 翻译自 Journaldev. Java线程是执行某些任务的轻量级进程.Java通过Thread类提供多线程支持,应用可以创建并发执行的多个线程. 应用中有两类线程——用户线程和守护线程.当启动应用时,main线程是创建的第一个用户线程,我们可以创建多个用户线程和守护线程.当所有用户进程执行完毕时,JVM终止程序. 可以对不同的线程设置不同的属性,但并不保证高优先级的线程在低优先级线程之前执行.线程调度器是操作系统的部分实现,当一个线程启动后,它的执行

JAVA线程应用Thread

java线程学习: 基本概念: 当一个程序开启的时候,会启动一个进程,在进程中会开启线程,如果只有一个线程,这个线程就称为主线程.如果进程停止,会先杀死线程再退出! java线程类:Thread  方法的作用: 如:start()方法启用线程,调用run方法启动进程. //定义线程类名;继承Thread类 class Demo extends Thread { //复写Runnable 的run方法; public void run() { for(int x=0;x<60;x++) { Sys

JAVA程序设计(18.1)----- 1多线程轮流打印 线程调度 线程池 synchronized wait notify 内部类

1.两个线程 一个打印A 一个打印B 另两个线程轮流进行打印工作 多线程初级应用 线程调度  线程池(预先建立N个线程,需要的程序直接调用,执行完毕后归还回线程池,典型的以空间换时间 synchronized wait notify  内部类使用 package com.lovo; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 类:测试 wait notify 用

JAVA程序设计(18.2)----- 5条线程按照给定规律轮流打印 线程调度 线程池 synchronized wait notify

这次没有使用 有名内部类 将程序控制数据.执行程序都独立出来了 5条线程按照给定规律轮流打印 线程调度 线程池 synchronized wait notify 代码如下: 1.独立出来的内部控制数据类 package com.lovo.homework02; /** * 类:将内部数据独立出来 方便修改和控制 * @author Abe * */ public class PrintThreadContext { /** * 允许执行的线程的key 初始值为3 (第4条线程) */ publi

沉淀再出发:再谈java的多线程机制

沉淀再出发:再谈java的多线程机制 一.前言 自从我们学习了操作系统之后,对于其中的线程和进程就有了非常深刻的理解,但是,我们可能在C,C++语言之中尝试过这些机制,并且做过相应的实验,但是对于java的多线程机制以及其中延伸出来的很多概念和相应的实现方式一直都是模棱两可的,虽然后来在面试的时候可能恶补了一些这方面的知识,但是也只是当时记住了,或者了解了一些,等到以后就会变得越来越淡忘了,比如线程的实现方式有两三种,线程池的概念,线程的基本生命周期等等,以及关于线程之间的多并发引起的资源的抢占

Java线程(二):线程同步synchronized和volatile

上篇通过一个简单的例子说明了线程安全与不安全,在例子中不安全的情况下输出的结果恰好是逐个递增的(其实是巧合,多运行几次,会产生不同的输出结果),为什么会产生这样的结果呢,因为建立的Count对象是线程共享的,一个线程改变了其成员变量num值,下一个线程正巧读到了修改后的num,所以会递增输出. 要说明线程同步问题首先要说明Java线程的两个特性,可见性和有序性.多个线程之间是不能直接传递数据交互的,它们之间的交互只能通过共享变量来实现.拿上篇博文中的例子来说明,在多个线程之间共享了Count类的