java 锁4
关于锁的分类 及 锁的灵活使用:
参见 http://blog.csdn.net/qaz13177_58_/article/details/21543515
有几句话说得相当不错:
锁的分类 :
同步分为类级别和对象级别,分别对应着类锁和对象锁。类锁是每个类只有一个,如果static的方法被synchronized关键字修饰,则在这个方法被执行前必须获得类锁;对象锁类同。
唤醒的含义:
只要是在synchronied块中的代码,没有对象锁是寸步难行的。其实唤醒一个线程就是重新允许这个线程去获得对象锁并向下运行。
———— 跟我的理解相同。 呵呵
notifyAll:
虽然notifyAll是对每个wait的对象都调用一次notify,但是这个还是有顺序的,每个对象都保存这一个等待对象链,调用的顺序就是这个链的顺序。其实启动等待对象链中各个线程的也是一个线程,在具体应用的时候,需要注意一下。
从
package test;
public class NotifyTest {
private String flag[] = { "true" }; class NotifyThread extends Thread {
public NotifyThread(String name) {
super(name);
} public void run() {
try {
sleep();// 推迟3秒钟通知
} catch (InterruptedException e) {
e.printStackTrace();
} synchronized (flag) {
flag[] = "false"; // notify并不会立即唤醒wait的进程,
// 必须等待当前同步块执行完毕!
//flag.notify(); flag.notifyAll(); // try {
// sleep(20000);// 推迟3秒钟通知
// } catch (InterruptedException e) {
// e.printStackTrace();
// } }
}
}; class WaitThread extends Thread {
public WaitThread(String name) {
super(name);
} public void run() {
synchronized (flag) {
while (flag[] != "false") {
System.out.println(getName() + " begin waiting!");
long waitTime = System.currentTimeMillis(); try {
flag.wait();
} catch (InterruptedException e) {
e.printStackTrace();
} waitTime = System.currentTimeMillis() - waitTime;
System.out.println("wait time :" + waitTime);
}
System.out.println(getName() + " end waiting!");
}
}
} public static void main(String[] args) throws InterruptedException {
System.out.println("Main Thread Run!");
NotifyTest test = new NotifyTest();
NotifyThread notifyThread = test.new NotifyThread("notify01");
WaitThread waitThread01 = test.new WaitThread("waiter01");
WaitThread waitThread02 = test.new WaitThread("waiter02");
WaitThread waitThread03 = test.new WaitThread("waiter03");
WaitThread waitThread04 = test.new WaitThread("waiter04");
WaitThread waitThread05 = test.new WaitThread("waiter05");
notifyThread.start();
waitThread01.start();
waitThread02.start();
waitThread03.start();
waitThread04.start();
waitThread05.start();
}
} 打印: Main Thread Run!
waiter02 begin waiting!
waiter01 begin waiting!
waiter03 begin waiting!
waiter04 begin waiting!
waiter05 begin waiting!
wait time :
waiter05 end waiting!
wait time :
waiter04 end waiting!
wait time :
waiter03 end waiting!
wait time :
waiter01 end waiting!
wait time :
waiter02 end waiting!
结果来看,应该等待对象链是一个栈,先获得对象锁的先放入栈中,notifyAll的时候反序唤醒。。———— 当然,我觉得这个,要是看到哦Object的源码就会十分清楚了吧!
写得太好了,再复制一段:
notify():
唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。
调用任意对象的notify()方法则导致因调用该对象的 wait()方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。
notifyAll():
唤醒所有等待的线程,注意唤醒的是notify之前wait的线程,对于notify之后的wait线程是没有效果的。?? 这个可能看源码才清楚, 不过先记住这个。
当obj.wait()方法返回后,线程A需要再次获得obj锁,才能继续执行。—— wait执行完后就不执行(下面的任何代码)了,亦即’阻塞‘的含义
通常,多线程之间需要协调工作:如果条件不满足,则等待;当条件满足时,等待该条件的线程将被唤醒。在Java中,这个机制的实现依赖于wait/notify。等待机制与锁机制是密切关联的。
例如:
synchronized(obj) {
while(!condition) {--------------------// 我还是不懂为什么一定要有一个while。— 懂了!完全可以没有while 。其实while可以换成if ,只是效果不一样!
------------------ while的意思是说,如果条件不满足,即使你唤醒了该线程也没用!它会又马上有陷入wait,如此循环,
------------------ if 的意思是说,不用说了吧 : 第一次不满足就wait,唤醒之后就不会再陷入。。继续执行后面的
------------------ 到底用哪个,当然是根据语境来判断的。 貌似while 用得多,更好用。。。
obj.wait();
}
obj.doSomething();
}
当线程A获得了obj锁后,发现条件condition不满足,无法继续下一处理,于是线程A就wait()。
在另一线程B中,如果B更改了某些条件,使得线程A的condition条件满足了,就可以唤醒线程A :
synchronized(obj) {
condition = true;
obj.notify();
}
注意一点:如果要把notify和wait方法放在一起用的话,必须先调用notify后调用wait,因为如果调用完wait,该线程就已经不是currentthread了 —— 表示不懂。。
一起用是指?一个方法/代码块既有notify又有wait ? 有这样的写法吗? 奇了怪了
notify
notify并不会立即唤醒wait的进程,而是,必须等待当前同步块执行完毕!
疑问:
某对象上并没有任何锁, notify/notifyAll会报错吗? 应该不会。。
尽管讨论了很多,现在仍然有一些疑惑
notifyAll 的作用是唤醒所有 ‘等待在此对象上的线程’—— 那么,是否有一个顺序呢? 不然的话,这些线程可以同时执行?显然, 不可以,因为,‘一个时间,只能有一个线程拥有一个对象的监视器’, 就是说其他线程想执行同时执行同一同步代码块的话,是不可能的!
那么、 到底是如何“唤醒所有”的呢
java api上是:
notifyAll
public final void notifyAll()
- Wakes up all threads that are waiting on this object's monitor. A thread waits on an object's monitor by calling one of the
wait
methods.The awakened threads will not be able to proceed until the current thread relinquishes the lock on this object. The awakened threads will compete in the usual manner with any other threads that might be actively competing to synchronize on this object; for example, the awakened threads enjoy no reliable privilege or disadvantage in being the next thread to lock this object.
This method should only be called by a thread that is the owner of this object's monitor. See the
notify
method for a description of the ways in which a thread can become the owner of a monitor.
继续讨论之前还是看看Thread类提供的方法吧!!!
理解Thread, 对理解线程相当关键!
发放
http://blog.sina.com.cn/s/blog_5ffe533a0101iwyl.html
http://www.360doc.com/content/12/1010/19/59141_240697086.shtml
http://docs.oracle.com/javase/6/docs/api/java/lang/Thread.html
好吧,现在确定的说一遍: 锁就是监视器,是针对某一个对象而已的。 这里的对象一般简单的java bean,可以理解为资源。
如果理解不了锁的概念,那么真是作孽,多线程的资源争用问题还如何继续理解??????? !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
sleep和wait的区别?
现在看来,这个已经是是否清楚了吧!
异:sleep并不会释放锁,而wait会。 __ 释放锁,意味着释放资源,依情况而定,有好处有坏处。。
sleep没有提供无参的sleep()方法。 而wait有。sleep安全? 而wait有多线程的安全问题? 没有!
wait需要在同步块(必须是synchronized, Lock都不行)中执行,sleep无需。
同:很明显,它们都导致了线程的阻塞(广义的阻塞)、 都需要捕获异常吧
http://www.cnblogs.com/zxyl/archive/2012/06/05/2536724.html
http://www.cnblogs.com/web100/p/sleep-wait.html
yeild, Thread的方法,让一个线程从running状态变为就绪状态,cpu让给优先级更高的线程,让出的时间? 不定。。
void java.lang.Thread.interrupt()
Interrupts this thread. Unless the current thread is interrupting itself, which is always permitted, the checkAccess method of this thread is invoked, which may cause a SecurityException to be thrown. If this thread is blocked in an invocation of the wait(), wait(long), or wait(long, int) methods of the Object class, or of the join(), join(long), join(long, int), sleep(long), or sleep(long, int), methods of this class, then its interrupt status will be cleared and it will receive an InterruptedException. If this thread is blocked in an I/O operation upon an interruptible channel then the channel will be closed, the thread's interrupt status will be set, and the thread will receive a java.nio.channels.ClosedByInterruptException. If this thread is blocked in a java.nio.channels.Selector then the thread's interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selector's wakeup method were invoked. If none of the previous conditions hold then this thread's interrupt status will be set. Interrupting a thread that is not alive need not have any effect.
java 锁4的更多相关文章
- java 锁!
问题:如何实现死锁. 关键: 1 两个线程ta.tb 2 两个对象a.b 3 ta拥有a的锁,同时在这个锁定的过程中,需要b的锁:tb拥有b的锁,同时在这个锁定的过程中,需要a的锁: 关键的实现难点是 ...
- Java锁(一)之内存模型
想要了解Java锁机制.引发的线程安全问题以及数据一致性问题,有必要了解内存模型,机理机制了解清楚了,这些问题也就应声而解了. 一.主内存和工作内存 Java内存模型分为主内存和工作内存,所有的变量都 ...
- Java锁的种类
转载自:---->http://ifeve.com/java_lock_see/ Java锁的种类以及辨析锁作为并发共享数据,保证一致性的工具,在JAVA平台有多种实现(如 synchroniz ...
- JAVA 锁
JAVA 锁 锁的概念 Java中的锁是控制资源访问的一种方式.它弥补了synchronized的可操作性不强的不足. Java的锁都实现了Lock接口.Lock结构定义了锁的基本操作. 函数 解释 ...
- JAVA锁的可重入性
机制:每个锁都关联一个请求计数器和一个占有他的线程,当请求计数器为0时,这个锁可以被认为是unhled的,当一个线程请求一个unheld的锁时,JVM记录锁的拥有者,并把锁的请求计数加1,如果同一个线 ...
- JAVA 锁之 Synchronied
■ Java 锁 1. 锁的内存语义 锁可以让临界区互斥执行,还可以让释放锁的线程向同一个锁的线程发送消息 锁的释放要遵循 Happens-before 原则(锁规则:解锁必然发生在随后的加锁之前) ...
- java锁与监视器概念 为什么wait、notify、notifyAll定义在Object中 多线程中篇(九)
在Java中,与线程通信相关的几个方法,是定义在Object中的,大家都知道Object是Java中所有类的超类 在Java中,所有的类都是Object,借助于一个统一的形式Object,显然在有些处 ...
- 自己动手写java锁
1.LockSupport的park和unpark方法的基本使用,以及对线程中断的响应性 LockSupport是JDK中比较底层的类,用来创建锁和其他同步工具类的基本线程阻塞原语.java锁和同步器 ...
- Java 锁的学习
个人学习整理,所有资料均来源于网络,非原创. 死锁的四个必要条件:互斥条件(Mutual exclusion):资源不能被共享,只能由一个进程使用.请求与保持条件(Hold and wait):已经得 ...
- java锁——wait,notify,synchronized
背景:这篇博客用来总结java锁相关的知识点,平时还是要自己多加练习 wait 和 notify以及notifyAll (1).方法介绍1.wait.notify以及notifyAll都是Object ...
随机推荐
- Sublime Text3安装JsHint
介绍 Sublime Text3使用jshint依赖Nodejs,SublimeLinter和Sublimelinter-jshint. NodeJs的安装省略. 安装SublimeLinter Su ...
- ASP.NET Aries 入门开发教程8:树型列表及自定义右键菜单
前言: 前面几篇重点都在讲普通列表的相关操作. 本篇主要讲树型列表的操作. 框架在设计时,已经把树型列表和普通列表全面统一了操作,用法几乎是一致的. 下面介绍一些差距化的内容: 1:树型列表绑定: v ...
- System.FormatException: GUID 应包含带 4 个短划线的 32 位数(xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx)。
在NHibernate数据库查询中出现了这个错误,由于是数据库是mysql的,当定义的字段为char(36)的时候就会出现这个错误. [解决方法] 将char(36) 改成varchar(40)就行了 ...
- .Net Core MVC 网站开发(Ninesky) 2.3、项目架构调整(续)-使用配置文件动态注入
上次实现了依赖注入,但是web项目必须要引用业务逻辑层和数据存储层的实现,项目解耦并不完全:另一方面,要同时注入业务逻辑层和数据访问层,注入的服务直接写在Startup中显得非常臃肿.理想的方式是,w ...
- 千呼万唤始出来,微软Power BI简体中文版官网终于上线了,中文文档也全了。。
前几个月时间,研究微软Power BI技术,由于没有任何文档和资料,只能在英文官网瞎折腾,同时也发布了英文文档的相关文章:系列文章,刚好上周把文章发布完,结果简体中文版上线了.哈哈,心里有苦啊,早知道 ...
- 做一个gulp+webpack+vue的单页应用开发架子
1.目标 最近项目上的事情不多,根据我自己的开发习惯,决定开发一些简单的开发架子,方便以后事情多的时候直接套用.本文讲的一个gulp+webpack+vue的单页应用架子,想要达到的目的: 可以通过命 ...
- Tesseract-OCR字符识别简介
OCR(Optical Character Recognition):光学字符识别,是指对图片文件中的文字进行分析识别,获取的过程.Tesseract:开源的OCR识别引擎,初期Tesseract引擎 ...
- java 利用ManagementFactory获取jvm,os的一些信息--转
原文地址:http://blog.csdn.net/dream_broken/article/details/49759043 想了解下某个Java项目的运行时jvm的情况,可以使用一些监控工具,比如 ...
- MAC Osx PHP安装指导
php.ini的位置 Mac OS X中没有默认的php.ini文件,但是有对应的模版文件php.ini.default,位于/private/etc/php.ini.default 或者说 /etc ...
- java使用websocket,并且获取HttpSession,源码分析
转载请在页首注明作者与出处 http://www.cnblogs.com/zhuxiaojie/p/6238826.html 一:本文使用范围 此文不仅仅局限于spring boot,普通的sprin ...