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 ) {...},同步代码块可以指定获取哪个对象上的锁。
④至于代码层面的解释理解之类的总结,以后遇到再详细学习。