Java中的Synchronized关键字
可以用来修饰同步方法:
像这样synchronized void f() {/*body*/}
也可以修饰同步语句块:
像这样synchronized(object){/*body*/}。
其中修饰同步方法还可以分为修饰static方法和实例方法。
其中修饰同步语句块还可以分为修饰instance变量,Object Reference对象引用,class 字面常量。
当synchronized作用在方法上时,锁住的便是对象实例(this);
所以synchronized void f() {/*body*/}和 void f(synchronized(this){/*body*/})是等价的。
当作用在静态方法时锁住的便是对象对应的Class实例,因为Class数据存在于永久带,因此静态方法锁相当于该类的一个全局锁;
当synchronized作用于某一个对象实例时,锁住的便是对应的代码块。
在HotSpot JVM实现中,锁有个专门的名字:对象监视器。
synchronized(class)
synchronized(this)
->线程各自获取monitor,不会有等待.
线程分别获取class和this,不会造成等待的例子:
- package com.hyy.test;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- public class SyncTest02 implements Runnable {
- private static boolean flag = true;
- private void testSync1() {
- synchronized (this) {
- for (int i = 0; i < 100; i++) {
- System.out.println("testSyncObject: " + i);
- }
- }
- }
- private void testSync2() {
- synchronized (SyncTest02.class) {
- for (int i = 0; i < 100; i++) {
- System.out.println("testSyncClass:" + i);
- }
- }
- }
- @Override
- public void run() {
- // TODO Auto-generated method stub
- if (flag) {
- flag = false;
- testSync1();
- } else {
- flag = true;
- testSync2();
- }
- }
- public static void main(String[] args) {
- ExecutorService exec = Executors.newFixedThreadPool(2);
- SyncTest02 sy1 = new SyncTest02();
- SyncTest02 sy2 = new SyncTest02();
- exec.execute(sy1);
- exec.execute(sy2);
- exec.shutdown();
- }
- }
synchronized(this)
synchronized(this)
->如果不同线程监视同一个实例对象,就会等待,如果不同的实例,不会等待.
不同线程监视同一个实例对象的例子:
- package com.hyy.test;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- public class SyncTest {
- public static void main(String[] args) {
- ExecutorService es = Executors.newFixedThreadPool(2);
- MyCount mc = new MyCount();
- MyThread mt1 = new MyThread(mc, "thread 1");
- MyThread mt2 = new MyThread(mc, "thread 2");
- es.execute(mt1);
- es.execute(mt2);
- es.shutdown();
- }
- }
- class MyThread extends Thread {
- MyCount count;
- String threadName;
- public MyThread(MyCount count, String threadName) {
- // TODO Auto-generated constructor stub
- this.count = count;
- this.threadName = threadName;
- }
- @Override
- public void run() {
- // TODO Auto-generated method stub
- for (int i = 0; i < 10; i++) {
- count.addOne(threadName);
- try {
- sleep(100L);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- }
- class MyCount {
- int i;
- public void addOne(String threadName) {
- synchronized (this) {
- i++;
- System.out.println(threadName + ":" + i);
- }
- }
- }
输出为
- thread 1:1
- thread 2:2
- thread 1:3
- thread 2:4
- thread 2:5
- thread 1:6
- thread 2:7
- thread 1:8
- thread 1:9
- thread 2:10
- thread 1:11
- thread 2:12
- thread 2:13
- thread 1:14
- thread 1:15
- thread 2:16
- thread 1:17
- thread 2:18
- thread 1:19
- thread 2:20
从输出上看,线程间出现了等待
不同线程监视不同实例对象的例子:
- package com.hyy.test;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- public class SyncTest {
- public static void main(String[] args) {
- ExecutorService es = Executors.newFixedThreadPool(2);
- MyCount mc = new MyCount("countONE");
- MyCount mc2 = new MyCount("countTWO");
- MyThread mt1 = new MyThread(mc, "thread 1");
- MyThread mt2 = new MyThread(mc2, "thread 2");
- es.execute(mt1);
- es.execute(mt2);
- es.shutdown();
- }
- }
- class MyThread extends Thread {
- MyCount count;
- String threadName;
- public MyThread(MyCount count, String threadName) {
- // TODO Auto-generated constructor stub
- this.count = count;
- this.threadName = threadName;
- }
- @Override
- public void run() {
- // TODO Auto-generated method stub
- for (int i = 0; i < 10; i++) {
- count.addOne(threadName);
- try {
- sleep(100L);
- } catch (InterruptedException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- }
- class MyCount {
- int i;
- String countName;
- public MyCount(String countName) {
- // TODO Auto-generated constructor stub
- this.countName = countName;
- }
- public void addOne(String threadName) {
- synchronized (this) {
- i++;
- System.out.println(threadName +"&&"+countName+ ":" + i);
- }
- }
- }
输出为
- thread 2&&countTWO:1
- thread 1&&countONE:1
- thread 2&&countTWO:2
- thread 1&&countONE:2
- thread 2&&countTWO:3
- thread 1&&countONE:3
- thread 2&&countTWO:4
- thread 1&&countONE:4
- thread 1&&countONE:5
- thread 2&&countTWO:5
- thread 2&&countTWO:6
- thread 1&&countONE:6
- thread 2&&countTWO:7
- thread 1&&countONE:7
- thread 1&&countONE:8
- thread 2&&countTWO:8
- thread 2&&countTWO:9
- thread 1&&countONE:9
- thread 1&&countONE:10
- thread 2&&countTWO:10
从输出上看,线程间没有发上等待。
synchronized(class)
synchronized(class)
->如果不同线程监视同一个实例或者不同的实例对象,都会等待.
不同线程监视不同实例对象的例子:
- package com.hyy.test;
- import java.util.concurrent.ExecutorService;
- import java.util.concurrent.Executors;
- public class SyncTest02 implements Runnable {
- private static boolean flag = true;
- private void testSync1() {
- synchronized (SyncTest02.class) {
- for (int i = 0; i < 100; i++) {
- System.out.println("testSyncObject: " + i);
- }
- }
- }
- private void testSync2() {
- synchronized (SyncTest02.class) {
- for (int i = 0; i < 100; i++) {
- System.out.println("testSyncClass:" + i);
- }
- }
- }
- @Override
- public void run() {
- // TODO Auto-generated method stub
- if (flag) {
- flag = false;
- testSync1();
- } else {
- flag = true;
- testSync2();
- }
- }
- public static void main(String[] args) {
- ExecutorService exec = Executors.newFixedThreadPool(2);
- SyncTest02 sy1 = new SyncTest02();
- SyncTest02 sy2 = new SyncTest02();
- exec.execute(sy1);
- exec.execute(sy2);
- exec.shutdown();
- }
- }