public synchronized void add(int value){ this.count += value; }
注意到此处的Synchronized关键字是加在方法声明处,这会告诉JVM,它是一个同步方法。
实例同步方法的锁,是加在拥有该方法的对象之上。因此每个实例的Synchronized关键字实际上都加在了不同的方法之上。同时只有一个线程能执行该实例的同步方法。
public static synchronized void add(int value){ count += value; }
上面是一个同步静态方法。同步静态方法的锁是加在类之上的,而相同的类在JVM中只有一个,一个类中只能有一个线程正在运行,不论它调用的是哪个静态方法。
public void add(int value){ synchronized(this){ this.count += value; } }
上面是一个非同步方法中的同步实例代码块。注意到同步代码块中Synchronized(this)中的this意味着当前实例对象。括号中的对象被称为监控对象。
监控对象中只有一个线程能运行,下面的两个方法都把锁加在了当前的对象上,因此两者是等效的。线程每次只能执行其中的一个方法。如果第二个同步代码块把Synchronized加在不同的对象上,则这两个方法有可能被两个线程同时执行。
public class MyClass { // 同步方法 public synchronized void log1(String msg1, String msg2){ log.writeln(msg1); log.writeln(msg2); } // 同步代码块 public void log2(String msg1, String msg2){ synchronized(this){ log.writeln(msg1); log.writeln(msg2); } } }
下面的两个方法,都把锁加在类上。
public class MyClass { //静态同步方法 public static synchronized void log1(String msg1, String msg2){ log.writeln(msg1); log.writeln(msg2); } //静态同步代码块 public static void log2(String msg1, String msg2){ synchronized(MyClass.class){ log.writeln(msg1); log.writeln(msg2); } } }
下面的这个例子,开启了两个线程,并且对同一个counter对象调用了add方法。每次只有一个线程能调用同一个实例的add方法,因为此处的Synchronized修饰的是对象。
// 柜员类 public class Counter{ long count = 0; // 此处有synchronized关键词修饰此实例方法 public synchronized void add(long value){ this.count += value; } } // 顾客类 public class CounterThread extends Thread{ protected Counter counter = null; public CounterThread(Counter counter){ this.counter = counter; } public void run() { for(int i=0; i<10; i++){ counter.add(i); } } } // 运行类 public class Example { public static void main(String[] args){ // 同一个counter实例 Counter counter = new Counter(); Thread threadA = new CounterThread(counter); Thread threadB = new CounterThread(counter); threadA.start(); threadB.start(); } }
java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查),将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用,从而保证了该变量的唯一性和准确性。
java中每个对象都有一把锁,线程可以通过synchronized关键字来获取对象上的锁。
内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。
注意:不能用synchronized修饰方法外面的语句块(类语句块),synchronized锁住的是对象,当初始化对象的时候,JVM在对象初始化完成之前会调用方法外面的语句块,这个时候对象还不存在,所以就不存在锁了。
②同步方法:(粗粒度锁):
1.修饰一般方法: public synchronized void method (){...},获取的是当前调用 对象this上的锁
2.修饰静态方法: public static synchronized void method (){...},获取当前类的 字节码对象上的锁
③同步代码块(细粒度锁):
synchronized ( obj ) {...},同步代码块可以指定获取哪个对象上的锁。
①首先是为什么要使用同步这个概念:
java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查),将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他线程的调用,从而保证了该变量的唯一性和准确性。
java中每个对象都有一把锁,线程可以通过synchronized关键字来获取对象上的锁。
内置锁会保护整个方法。在调用该方法前,需要获得内置锁,否则就处于阻塞状态。
注意:不能用synchronized修饰方法外面的语句块(类语句块),synchronized锁住的是对象,当初始化对象的时候,JVM在对象初始化完成之前会调用方法外面的语句块,这个时候对象还不存在,所以就不存在锁了。
②同步方法:(粗粒度锁):
1.修饰一般方法: public synchronized void method (){...},获取的是当前调用 对象this上的锁
2.修饰静态方法: public static synchronized void method (){...},获取当前类的 字节码对象上的锁
③同步代码块(细粒度锁):
synchronized ( obj ) {...},同步代码块可以指定获取哪个对象上的锁。
④至于代码层面的解释理解之类的总结,以后遇到再详细学习。