JAVA学习笔记--多线程(三)synchronized实现线程同步
2016-06-06 18:48
393 查看
JAVA中对同步控制主要通过synchronized关键字
wait() notify()和notifyAll()方法
1.synchronized 的用法
每个类实例对应一把锁,每个synchronized方法都必须获得调用该方法的类实例的锁才能执行,否则发生线程阻塞
方法一旦执行,就独占锁,直到该方法返回时,才释放锁,此后被阻塞的线程才能获得该锁。
A . 声明方法时,放在范围操作符和返回值之间。
作用:表示一次只能有一个线程进入该方法,其他的线程想在此时调用这个方法,只能是排队等待
只有当当前的线程执行完该方法以后,其他的线程才能进入。
B. synchronized代码块
格式:synchronized(variable){
code;
}
一次只能有一个线程进入该代码块
C . synchronized(object)
格式:synchronized(object o){
code;
}
线程获得的是对象锁。对象锁会在下一篇笔记里详细学习,到时候再贴上链接
D . synchronized(Class)
synchronized的参数是类,只要线程进入,则该类中的所有操作都不能进进行,包括静态变量和静态方法。
synchronized代码块示例:
输出结果:
Thread-0进入taskA
Thread-0synchronized in taskA()
Thread-1进入taskA
Thread-1synchronized in taskA()
Thread-0进入taskB
Thread-1进入taskB
Thread-0synchronized in taskB()
Thread-1synchronized in taskB()
这个例子想表达的意思是:
当两个并发线程访问同一个对象中的synchronized同步代码块时,一个时间内只能有一个线程得到执行,另一个线程必须等待当前线程完成后才能得到执行。然而,当一个线程访问synchronized同步代码块时,另一个线程仍然可以访问该对象的非synchronized同步代码块。这也是为什么结果中当Thread-0和Thread-1都可以打印出“进入代taskB”语句。
wati(),notify()和 notifyAll()
调用任意对象的wait()方法,都会导致线程阻塞,并且该对象上的锁被释放
调用任意对象的notify()方法,则会随机选择一个阻塞状态的进程,并解除该线程的阻塞状态。
注意:
1.这两个方法是每个对象都具有的,而不是只属于线程类。
2.如果要把notify和wait方法放在一起用的话,必须先调用notify后调用wait,因为如果调用完wait,那么那个线程就会进入等待队列,该线程就已经不是current
thread了。
3.调用wait()方法前的判断最好用while,而不用if;while可以实现被wakeup后thread再次作条件判断;而if则只能判断一次。
4.除了
notify(),还有一个方法 notifyAll() 也可起到类似作用,唯一的区别在于,调用 notifyAll() 方法将把因调用该对象的wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然,只有获得锁的那一个线程才能进入可执行状态。
.
wait() notify()和notifyAll()方法
1.synchronized 的用法
每个类实例对应一把锁,每个synchronized方法都必须获得调用该方法的类实例的锁才能执行,否则发生线程阻塞
方法一旦执行,就独占锁,直到该方法返回时,才释放锁,此后被阻塞的线程才能获得该锁。
A . 声明方法时,放在范围操作符和返回值之间。
作用:表示一次只能有一个线程进入该方法,其他的线程想在此时调用这个方法,只能是排队等待
只有当当前的线程执行完该方法以后,其他的线程才能进入。
B. synchronized代码块
格式:synchronized(variable){
code;
}
一次只能有一个线程进入该代码块
C . synchronized(object)
格式:synchronized(object o){
code;
}
线程获得的是对象锁。对象锁会在下一篇笔记里详细学习,到时候再贴上链接
D . synchronized(Class)
synchronized的参数是类,只要线程进入,则该类中的所有操作都不能进进行,包括静态变量和静态方法。
synchronized代码块示例:
package synchronizedTest; public class Tasks implements Runnable{ public void taskA() { System.out.println(Thread.currentThread().getName()+"进入taskA"); synchronized (this) { System.out.println(Thread.currentThread().getName()+"synchronized in taskA()"); try { //用sleep()模拟任务耗时 Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } } } public void taskB() { System.out.println(Thread.currentThread().getName()+"进入taskB"); synchronized (this) { System.out.println(Thread.currentThread().getName()+"synchronized in taskB()"); //用sleep()模拟任务耗时 try { Thread.sleep(2000); } catch (Exception e) { e.printStackTrace(); } } } @Override public void run() { // TODO Auto-generated method stub taskA(); taskB(); } }
package synchronizedTest; public class Test { public static void main(String [] args){ Runnable tasks1= new Tasks(); Thread th1=new Thread(tasks1); Thread th2=new Thread(tasks1); th1.start(); th2.start(); } }
输出结果:
Thread-0进入taskA
Thread-0synchronized in taskA()
Thread-1进入taskA
Thread-1synchronized in taskA()
Thread-0进入taskB
Thread-1进入taskB
Thread-0synchronized in taskB()
Thread-1synchronized in taskB()
这个例子想表达的意思是:
当两个并发线程访问同一个对象中的synchronized同步代码块时,一个时间内只能有一个线程得到执行,另一个线程必须等待当前线程完成后才能得到执行。然而,当一个线程访问synchronized同步代码块时,另一个线程仍然可以访问该对象的非synchronized同步代码块。这也是为什么结果中当Thread-0和Thread-1都可以打印出“进入代taskB”语句。
wati(),notify()和 notifyAll()
调用任意对象的wait()方法,都会导致线程阻塞,并且该对象上的锁被释放
调用任意对象的notify()方法,则会随机选择一个阻塞状态的进程,并解除该线程的阻塞状态。
注意:
1.这两个方法是每个对象都具有的,而不是只属于线程类。
2.如果要把notify和wait方法放在一起用的话,必须先调用notify后调用wait,因为如果调用完wait,那么那个线程就会进入等待队列,该线程就已经不是current
thread了。
3.调用wait()方法前的判断最好用while,而不用if;while可以实现被wakeup后thread再次作条件判断;而if则只能判断一次。
4.除了
notify(),还有一个方法 notifyAll() 也可起到类似作用,唯一的区别在于,调用 notifyAll() 方法将把因调用该对象的wait() 方法而阻塞的所有线程一次性全部解除阻塞。当然,只有获得锁的那一个线程才能进入可执行状态。
.
相关文章推荐
- Python3写爬虫(四)多线程实现数据爬取
- C#实现多线程的同步方法实例分析
- C#线程间不能调用剪切板的解决方法
- 浅谈chuck-lua中的多线程
- C#简单多线程同步和优先权用法实例
- C#多线程学习之(四)使用线程池进行多线程的自动管理
- C#多线程编程中的锁系统(三)
- C#线程同步的三类情景分析
- C#获取进程或线程相关信息的方法
- 简单对比C#程序中的单线程与多线程设计
- C#停止线程的方法
- 解析C#多线程编程中异步多线程的实现及线程池的使用
- C#子线程更新UI控件的方法实例总结
- C#多线程学习之(六)互斥对象用法实例
- C#线程队列用法实例分析
- 基于一个应用程序多线程误用的分析详解
- C#多线程学习之(三)生产者和消费者用法分析
- C#多线程学习之(一)多线程的相关概念分析
- C#多线程之Thread中Thread.IsAlive属性用法分析
- 分享我在工作中遇到的多线程下导致RCW无法释放的问题