java笔记(九):synchronized
来源:互联网 发布:移动硬盘与mac连接 编辑:程序博客网 时间:2024/05/16 12:05
synchronized常用来保证线程安全,作为java中比较复杂的一个关键字,有必要专门进行一次总结。
大体上来说,用该关键字修饰方法或代码块时,能保证同一时刻,只能有一个线程访问该属性或代码块。
关于synchronized(this)同步代码块,有如下两点需要注意:
- 对于同一个对象的所有synchronized(this)同步代码块,只能有某一个该代码块被某一个线程执行
- 某个线程访问synchronized(this)代码块时,其他线程仍可访问非synchronized(this)代码块
另外需要强调的是,以上规则只对同一个对象实例化的多个线程有效,即多线程需要由同一个对象实例化。
public class Test{ public static void main(String[] arcgs) throws Exception { //用来实例化的对象 ThreadTest threadTest = new ThreadTest(); Thread thread1 = new Thread(threadTest); Thread thread2 = new Thread(threadTest); thread1.start(); thread2.start(); }}class ThreadTest implements Runnable{ private int count = 0; public void run(){ synchronized(this){ for(int i = 0;i<4;i++){ count++; System.out.println(Thread.currentThread().getName()+" "+count); } } }}/*** Thread-0 1* Thread-0 2* Thread-0 3* Thread-0 4* Thread-1 5* Thread-1 6* Thread-1 7* Thread-1 8* /
当然对于非synchronized(this)代码块,其他线程仍可以执行。
public class Test{ public static void main(String[] arcgs) throws Exception { //用来实例化的对象 ThreadTest threadTest = new ThreadTest(); Thread thread1 = new Thread(threadTest); Thread thread2 = new Thread(threadTest); thread1.start(); thread2.start(); }}class ThreadTest implements Runnable{ private int count = 0; public void run(){ for(int i = 0;i<3;i++){ System.out.println(Thread.currentThread().getName()+" "+i); } synchronized(this){ for(int i = 0;i<3;i++){ count++; System.out.println(Thread.currentThread().getName()+" synchronized "+" "+count); } } }}/**Thread-0 0Thread-1 0Thread-0 1Thread-1 1Thread-0 2Thread-1 2Thread-0 synchronized 1Thread-0 synchronized 2Thread-0 synchronized 3Thread-1 synchronized 4Thread-1 synchronized 5Thread-1 synchronized 6* /
为了更好地理解synchronized关键字修饰方法的意义,看下面的例子:
ThreadTest threadTest = new ThreadTest();Thread thread1 = new Thread(new Runnable(){ public void run(){ threadTest.test0(); }});Thread thread2 = new Thread(new Runnable(){ public void run(){ threadTest.test1(); }});thread1.start();thread2.start();class ThreadTest { private int count = 0; public synchronized void test0(){ for(int i = 0;i<3;i++){ count++; System.out.println(Thread.currentThread().getName()+" synchronized0 "+" "+count); } } public synchronized void test1(){ for(int i = 0;i<3;i++){ count++; System.out.println(Thread.currentThread().getName()+" synchronized1 "+" "+count); } }}/**Thread-0 synchronized0 1Thread-0 synchronized0 2Thread-0 synchronized0 3Thread-1 synchronized1 4Thread-1 synchronized1 5Thread-1 synchronized1 6* /
虽然没有实现Runnable接口,但由于是在建立的内部类中运行,因此仍然实现了单线程的访问。
注意理解synchronized(this)的意思。
下面的代码等做到单线程执行吗?
ThreadTest threadTest = new ThreadTest();Thread thread1 = new Thread(new Runnable(){ public void run(){ synchronized(this){ threadTest.test0(); } }});Thread thread2 = new Thread(new Runnable(){ public void run(){ synchronized(this){ threadTest.test1(); } }});thread1.start();thread2.start();class ThreadTest { private int count = 0; public void test0(){ for(int i = 0;i<3;i++){ count++; System.out.println(Thread.currentThread().getName()+" synchronized0 "+" "+count); } } public void test1(){ for(int i = 0;i<3;i++){ count++; System.out.println(Thread.currentThread().getName()+" synchronized1 "+" "+count); } }}/** 一种可能的输出结果Thread-1 synchronized1 2Thread-0 synchronized0 2Thread-1 synchronized1 3Thread-0 synchronized0 4Thread-1 synchronized1 5Thread-0 synchronized0 6* /
原因在于,synchronized(this)的目的是获取当前对象的锁,但代码中两次new Thread()中的参数是新建的两个内部类,无法起到互斥的作用。只需要将synchronized(this)改为synchronized(threadTest),就可以得到单线程运行的结果,如下:
/** 一种可能的输出结果Thread-0 synchronized0 1Thread-0 synchronized0 2Thread-0 synchronized0 3Thread-1 synchronized1 4Thread-1 synchronized1 5Thread-1 synchronized1 6* /
在 Java 中,不光是类对象,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。
阅读全文
0 0
- java笔记(九):synchronized
- 疯狂Java学习笔记(68)-----------synchronized
- Java学习笔记(68)-----------synchronized
- Java synchronized 学习笔记
- java学习笔记(九)
- Java笔记(九) 异常
- Java学习笔记(九)
- Java学习笔记(九)
- Java学习笔记(九)
- java学习笔记(九)
- Java学习笔记(九)
- think in java笔记: synchronized
- 线程笔记(synchronized)
- Effective Java学习笔记(九)
- Java Web学习笔记(九)spring
- java无难事笔记(九)
- Java学习笔记(九):Map.keyset()
- Java学习笔记九(泛型)
- Android性能优化之使用线程池处理异步任务
- 各类运算符优先级
- 【Java基础之多线程】代码库(二)
- 开发工具收集
- STM8S TIM2 输出PWM初始化函数
- java笔记(九):synchronized
- 数据链路层
- Material Design 之 Toolbar 开发实践总结
- Java值传递与引用传递
- MySQL中的触发器
- PDO PHP
- 欢迎使用CSDN-markdown编辑器
- 【7月3日】LeetCode刷题日志(一):TwoSum
- 在django中使用 MEDIA_URL 和 MEDIA_ROOT