Java关于Synchronized关键字在不同位置使用的理解

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();
	}

}



  • 5
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值