您的位置:首页 > 编程语言 > Java开发

关于java多线程浅析三:每个对象都有的方法

2017-05-11 23:44 197 查看
先明确一下一些基本的概念。

1 串行、并行与并发的区别:

不搞那些晦涩的定义,讲一个简单的例子,可能不恰当,但基本上是这个意思。

就拿一个很简单的例子来说吧,下班回家后,你想做饭,但你又想打晋级赛,你想了想,算了,还是打完了晋级赛再做饭吧,好吧,这就是串行,做完一件事再做另外一件事;还有一种方法是,你选择玩亚索发大招的瞬间抽个空去厨房把菜洗了,当然你会死的很惨,这样打一会LOL再洗个菜,然后回来继续放你的QWER,这就是并发。还有就是你让你女朋友去做饭,你去打LOL,(当然这样你也会死得很惨),这就是并行。

2 线程安全与同步

线程安全就是指在多线程运行程序的情况下,每一次的运行结果都是和单线程实现相同逻辑代码的运行结果一致,或者说是能确保每一次运行得到的结果都是期望正确的值,那就是线程安全的。

那什么是同步呢?同步就是指通过人为的控制和调度,保证共享资源的多线程访问成为线程安全,来保证结果的准确。说白了,就是要对多线程进行有效的管理,以保证每个线程都能正确的访问共享资源。

那么问题就出来了,怎么才能对多线程进行有效的控制和调度呢?既然要到线程进行控制,那么首先就需要有这么一个监控器来进行监控。



监控器Monitor是java中用以实现线程之间的互斥与协作的一种机制,可以把Monitor简单理解成对象或者class的锁。每一个对象都有成为Monitor的潜质,当然,每一个对象有且仅有一个Monitor。它的作用就是来监测并发代码的重入。在非多线程编码时该监视器不发挥作用,反之如果在synchronized 范围内,监视器发挥作用。每个 Monitor在某个时刻,只能被一个线程拥有,该线程就是 “Active Thread”,而其它线程都是 “Waiting Thread”,分别在两个队列 “ Entry Set”和 “Wait Set”里面等候。在 “Entry Set”中等待的线程状态是 “Waiting for monitor entry”(等待锁的获取),而在 “Wait Set”中等待的线程状态是 “in Object.wait()”(等待线程被唤醒)。

举了简单的例子说明:

public class MyThread {

public static void main(String[] args) {
try {
ThreadA t1 = new ThreadA("t1");
synchronized (t1) {
System.out.println(Thread.currentThread().getName()+"线程启动线程 t1");
t1.start();

System.out.println(Thread.currentThread().getName()+"线程等待被唤醒");
t1.wait();

System.out.println(Thread.currentThread().getName()+"线程继续执行");
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}

}

class ThreadA extends Thread{
public ThreadA(String name){
super(name);
}

public void run(){
synchronized (this) {
System.out.println(Thread.currentThread().getName()+"线程执行 notify 方法");
notify();
}
}
}


上面的代码很简单,就是在main函数里启动一个继承了Thread类的线程t1,然后调用wait()方法。在t1的run()方法里调用notify()方法。但值得注意的是,我们在main函数以及ThreadA类里的run方法上,都用到了synchronized关键字,一个传递的是对象t1,一个是this关键字,但在这段代码里,可以确定它们都是这个t1对象。回顾一下上面说过的每个对象都有且仅有一个monitor,再看一下运行的结果,再进行进一步分析:

main线程启动线程 t1
main线程等待被唤醒
t1线程执行 notify 方法
main线程继续执行


明明是代码里是t1.wait(),为什么等待的确实main线程呢?这是因为wait函数的语义是使当前线程等待,也就是途中所描述的“Active Thread”。当main函数执行 synchronized (t1) 代码段时,main线程获得了对象t1 的 monitor,当t1.start( )时,t1线程也执行相同语义的代码synchronized (this) 时,因为monitor已经被main线程所获得,t1只能进入Wait Set”里面等候。当调用t1.wait()时,就会将正在monitor中的处于“Active Thread”状态的main线程置于“Wait Set”里面等待,也就是浅析二中线程状态图中的“等待Blocked”状态,此时正在Wait Set”里面等待的t1线程就马上获得了CPU的执行权,变成了Active Thread”。再调用notify()方法后,main线程进入“锁定Blocked”状态,随时等待t1线程继续执行完毕后得到t1释放的monitor,进入就绪状态,然后main函数执行完毕。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线程 java 并发
相关文章推荐