首页 > 代码库 > java 锁4

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(1000);// 推迟3秒钟通知            } catch (InterruptedException e) {                e.printStackTrace();            }            synchronized (flag) {                flag[0] = "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[0] != "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 :999waiter05 end waiting!wait time :999waiter04 end waiting!wait time :999waiter03 end waiting!wait time :1000waiter01 end waiting!wait time :1000waiter02 end waiting!
View Code

 

结果来看,应该等待对象链是一个栈,先获得对象锁的先放入栈中,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.   ————打搅sleep睡觉专用的? 好难理解。以后再看。  

  

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 threads 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 threads interrupt status will be set and it will return immediately from the selection operation, possibly with a non-zero value, just as if the selectors wakeup method were invoked.If none of the previous conditions hold then this threads interrupt status will be set.Interrupting a thread that is not alive need not have any effect.
View Code