关闭

【java】synchronized 关键字

213人阅读 评论(0) 收藏 举报
分类:

大一的时候对这个东西敬而远之,可能是因为刚学java,完全不理解,现在是时候搞清楚它了。

字面意思是同步,翻译过来挺绕的。从同步和异步这对概念来入手,是比较难理解的。其实只要围绕“互斥”这个概念,synchronized关键字就很好理解!

大二操作系统会介绍互斥的概念,与java中的含义完全相同,只不过一个是操作系统中的,一个是java jvm的,应用层次不同而已。

1.我理解的java中的互斥是,在多线程环境下,对同一数据进行更新操作的互斥,也即只有当一个线程执行完更新后,另一个线程才可以开始。这也是synchronized关键字的用处。

举个例子,老生常谈了,存钱的例子。比如A的账户是100,现准备在atm中存入100,在这个过程中,A的朋友正在用手机银行,也试图往A的账户存入100。那么,在理论上就会有一个t1时刻,在t1时刻,atm机获取了A账户余额100,还未加100,同时A友的手机银行后台也获取了余额100,然后再各自进行加100的操作,更新A的账户,可想而知,A最后只有200,而非300。

问题出在对账户的更新必须互斥,atm在更新的时候,其他方式就必须等待,atm更新完了,才能开始其他的更新操作。这就是互斥。

2.锁的概念。这也是synchronized用法中的一个关键点。锁其实是互斥的标志。定义了哪些更新操作需要互斥。比如在A更新时,B的账户更新就不应该被阻塞,A和B的账户更新完全没有关系。而A的atm更新就应该和A的手机银行更新互斥。所以,锁定义了互斥的条件。


java中的锁

方法锁:

在非static方法上加synchronized关键字,那么同一个对象的所有的带有synchronized的方法全部互斥;锁就是调用的对象。所有的线程要想调用这个方法,必须拿到该对象的锁,锁只能被一个线程拥有。

块锁:

锁一段代码,需要指定锁是什么,可以是类锁可以使对象锁。块锁的优势是可以精确锁的范围,提高性能。

静态方法锁:

只能应用于静态方法,线程需要拿到类的锁才可以执行,不同对象也会被互斥。

例子:

package main;

public class Main {

	public static void main(String[] args) {
        new Main().f();
	}
	
	public void f(){
		final Acount acount1 = new Acount();
		for(int j=0;j<10;j++){
			Thread thread = new Thread(new Runnable() {
				
				@Override
				public void run() {
					acount1.add1(100);
				}
			});
			thread.start();
		}
		try {
			Thread.sleep(1000);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println("1结果: "+acount1.getMoney());
	}
}

package main;


public class Acount{

	private int money = 0;

	public synchronized void add(int inc){
		System.out.println("*********开始********");
		int temp = this.money;
		temp = temp + inc;
		this.money = temp;
		System.out.println(money);
		System.out.println("*********结束********");
	}
	
	public void add1(int inc){
		synchronized (this) {
			System.out.println("*********开始********");
			int temp = this.money;
			temp = temp + inc;
			this.money = temp;
			System.out.println(money);
			System.out.println("*********结束********");
		}
	}

	public int getMoney() {
		return money;
	}
}

最后打印结果的时候,需要等待的原因是打印语句执行时,可能之前的更新线程还未全部执行完毕。

推荐一篇很好的博客:http://www.cnblogs.com/paddix/p/5367116.html

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:99254次
    • 积分:2945
    • 等级:
    • 排名:第12065名
    • 原创:202篇
    • 转载:9篇
    • 译文:0篇
    • 评论:31条
    最新评论