java synchronized详解--synchronized方法
2017-02-17 17:25
260 查看
上一章讲了synchronized代码块,这章说一下synchronize方法,及synchronized代码块与synchronized方法的联系
上一章说的synchronized代码块,主要说了synchronized锁(类似现实中的锁)的重要性和注意项
这章说一下synchronized修饰的方法的关键点和注意项
如果你拜读了java官方文档,你会知道synchronized方法也有锁(类似现实中的锁),那么它的锁(类似现实中的锁)是什么呢,下面通过代码和运行结果来找出答案
结构简述:
定义了一个资源PrintDemo3,一个线程类ThreadDemo3,一个测试类TestThread,在测试类中创建两个线程对象,两个线程对象都通过run方法访问资源PrintDemo.printCount方法
上面代码在PrintDemo3.printCount()上加了synchronized修饰符,表示这个方法是加锁了的。之后定义了两个PrintDemo3对象PD、PD3和两个ThreadDemo3线程对象T1、T2,并把PD、PD3分别传给T1、T2,见test1方法
运行后查看结果:
从结果得出,资源被两个线程同时访问了,synchronized方法的锁没有起作用。原因我们稍后再说,稍稍改一下代码
第二幕:
改一下代码:ThreadDemo3 T2 = new ThreadDemo3( “Thread - 2 “, PD3 ) 中的PD3改为PD
修改代码后运行,查看结果
从结果得出,实现了资源被线程独享
第一幕和第二幕代码的不同处只有传给两个线程的PrintDemo3对象不同。第一幕中两个线程T1、T2分别传递了PD、PD3。而第二幕中两个线程T1、T2都传递了PD。所以可以猜想,造成结果不同的原因也是由于锁(类似现实中的锁)的不同引起的。而修饰方法的synchronized的锁(类似现实中的锁)是synchronized方法所在类的对象实例,相当于synchronized方法等于方法里的synchronized(this)代码块,这里的this就是synchronized方法所在类的对象实例。
为了验证这个猜想,看第二种场景
场景二的代码与场景一99%是一样的,不同之处在PrintDemo3.printCount()方法上,把方法修饰符synchronized移到了此方法内,并把this作为synchronized的锁(类似现实中的锁)
第三幕:
两个线程T1、T2分别传递了PD、PD3
运行test1()方法并查看结果:
第四幕:
修改test1()方法代码为:
也就是两个线程T1、T2都传递了PD
运行test1()方法并查看结果:
从结果得出,实现了资源被线程独享
比较第一幕和第三幕,第二幕和第四幕,可以发现如下
以上说了synchronized应用级的用法,关于内部原理实现,我的水平还有待提高,请看下面关于原理的讲解:
http://www.importnew.com/23511.html
https://www.quora.com/How-does-synchronize-work-in-Java
http://blog.takipi.com/5-things-you-didnt-know-about-synchronization-in-java-and-scala/
http://gee.cs.oswego.edu/dl/cpj/jmm.html
上一章说的synchronized代码块,主要说了synchronized锁(类似现实中的锁)的重要性和注意项
这章说一下synchronized修饰的方法的关键点和注意项
如果你拜读了java官方文档,你会知道synchronized方法也有锁(类似现实中的锁),那么它的锁(类似现实中的锁)是什么呢,下面通过代码和运行结果来找出答案
结构简述:
定义了一个资源PrintDemo3,一个线程类ThreadDemo3,一个测试类TestThread,在测试类中创建两个线程对象,两个线程对象都通过run方法访问资源PrintDemo.printCount方法
第一种场景:资源加锁在synchronized方法上
第一幕:package com.yy.test; /** * Created by skyler on 2017/2/17. */ class PrintDemo3 { public synchronized void printCount() { try { for(int i = 10; i > 0; i--) { System.out.println("Counter --- " + i ); } }catch (Exception e) { System.out.println("Thread interrupted."); } } } class ThreadDemo3 extends Thread { private Thread t; private String threadName; PrintDemo3 PD; ThreadDemo3( String name, PrintDemo3 pd) { threadName = name; PD = pd; } public void run() { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } PD.printCount(); System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { TestThread tt = new TestThread(); tt.test1(); } public void test1() { PrintDemo3 PD = new PrintDemo3(); PrintDemo3 PD3 = new PrintDemo3(); ThreadDemo3 T1 = new ThreadDemo3( "Thread - 1 ", PD ); ThreadDemo3 T2 = new ThreadDemo3( "Thread - 2 ", PD3 ); T1.start(); T2.start(); // wait for threads to end try { T1.join(); T2.join(); }catch( Exception e) { System.out.println("Interrupted"); } } }
上面代码在PrintDemo3.printCount()上加了synchronized修饰符,表示这个方法是加锁了的。之后定义了两个PrintDemo3对象PD、PD3和两个ThreadDemo3线程对象T1、T2,并把PD、PD3分别传给T1、T2,见test1方法
运行后查看结果:
Starting Thread - 1 Starting Thread - 2 Counter --- 10 Counter --- 9 Counter --- 8 Counter --- 7 Counter --- 6 Counter --- 10 Counter --- 9 Counter --- 8 Counter --- 7 Counter --- 6 Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 2 exiting. Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 1 exiting.
从结果得出,资源被两个线程同时访问了,synchronized方法的锁没有起作用。原因我们稍后再说,稍稍改一下代码
第二幕:
改一下代码:ThreadDemo3 T2 = new ThreadDemo3( “Thread - 2 “, PD3 ) 中的PD3改为PD
修改代码后运行,查看结果
Starting Thread - 1 Starting Thread - 2 Counter --- 10 Counter --- 9 Counter --- 8 Counter --- 7 Counter --- 6 Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 1 exiting. Counter --- 10 Counter --- 9 Counter --- 8 Counter --- 7 Counter --- 6 Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 2 exiting.
从结果得出,实现了资源被线程独享
第一幕和第二幕代码的不同处只有传给两个线程的PrintDemo3对象不同。第一幕中两个线程T1、T2分别传递了PD、PD3。而第二幕中两个线程T1、T2都传递了PD。所以可以猜想,造成结果不同的原因也是由于锁(类似现实中的锁)的不同引起的。而修饰方法的synchronized的锁(类似现实中的锁)是synchronized方法所在类的对象实例,相当于synchronized方法等于方法里的synchronized(this)代码块,这里的this就是synchronized方法所在类的对象实例。
为了验证这个猜想,看第二种场景
第二种场景:资源加锁在方法内的synchronized(this)代码块上
package com.yy.test; /** * Created by yaoliang on 2017/2/17. */ class PrintDemo3 { public void printCount() { synchronized(this) { try { for(int i = 10; i > 0; i--) { System.out.println("Counter --- " + i ); } }catch (Exception e) { System.out.println("Thread interrupted."); } } } } class ThreadDemo3 extends Thread { private Thread t; private String threadName; PrintDemo3 PD; ThreadDemo3( String name, PrintDemo3 pd) { threadName = name; PD = pd; } public void run() { try { Thread.sleep(20); } catch (InterruptedException e) { e.printStackTrace(); } PD.printCount(); System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { TestThread tt = new TestThread(); tt.test1(); } public void test1() { PrintDemo3 PD = new PrintDemo3(); PrintDemo3 PD3 = new PrintDemo3(); ThreadDemo3 T1 = new ThreadDemo3( "Thread - 1 ", PD ); ThreadDemo3 T2 = new ThreadDemo3( "Thread - 2 ", PD3 ); T1.start(); T2.start(); // wait for threads to end try { T1.join(); T2.join(); }catch( Exception e) { System.out.println("Interrupted"); } } }
场景二的代码与场景一99%是一样的,不同之处在PrintDemo3.printCount()方法上,把方法修饰符synchronized移到了此方法内,并把this作为synchronized的锁(类似现实中的锁)
第三幕:
两个线程T1、T2分别传递了PD、PD3
运行test1()方法并查看结果:
Starting Thread - 1 Starting Thread - 2 Counter --- 10 Counter --- 9 Counter --- 8 Counter --- 7 Counter --- 10 Counter --- 6 Counter --- 9 Counter --- 8 Counter --- 7 Counter --- 6 Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 2 exiting. Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 1 exiting.
第四幕:
修改test1()方法代码为:
ThreadDemo3 T1 = new ThreadDemo3( "Thread - 1 ", PD ); ThreadDemo3 T2 = new ThreadDemo3( "Thread - 2 ", PD );
也就是两个线程T1、T2都传递了PD
运行test1()方法并查看结果:
Starting Thread - 1 Starting Thread - 2 Counter --- 10 Counter --- 9 Counter --- 8 Counter --- 7 Counter --- 6 Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 1 exiting. Counter --- 10 Counter --- 9 Counter --- 8 Counter --- 7 Counter --- 6 Counter --- 5 Counter --- 4 Counter --- 3 Counter --- 2 Counter --- 1 Thread Thread - 2 exiting.
从结果得出,实现了资源被线程独享
比较第一幕和第三幕,第二幕和第四幕,可以发现如下
结论:
synchronized方法等于方法中加入synchronized(this)代码块,也就是synchronized修饰方法时,synchronized的锁(类似现实中的锁)是调用这个方法的类的对象实例,如PD.printCount(),此时synchronized锁就是PD;而PD3.printCount(),此时synchronized锁就是PD3以上说了synchronized应用级的用法,关于内部原理实现,我的水平还有待提高,请看下面关于原理的讲解:
http://www.importnew.com/23511.html
https://www.quora.com/How-does-synchronize-work-in-Java
http://blog.takipi.com/5-things-you-didnt-know-about-synchronization-in-java-and-scala/
http://gee.cs.oswego.edu/dl/cpj/jmm.html
相关文章推荐
- Java: synchronized详解,静态同步方法,普通同步方法,同步代码块
- java中synchronized(同步代码块和同步方法)详解及区别
- Java锁机制Synchronized方法详解
- Java中synchronized关键字修饰方法同步的用法详解
- Java synchronized 对象锁与类锁的区别、同步代码块与同步方法的区别 详解
- Java synchronized 对象锁与类锁的区别、同步代码块与同步方法的区别 详解
- Java this 关键字的使用方法详解
- java synchronized详解
- java synchronized详解[转]
- java synchronized详解
- Java中main方法的格式详解
- java synchronized详解
- java synchronized详解
- 图文详解Java环境变量配置方法
- FckEditor for java 2.4的JSP 配置方法详解
- java synchronized详解
- Java构造和解析Json数据的两种方法详解一
- 详解Java解析XML的四种方法
- java synchronized详解
- binarySearch()方法详解 java