java的同步块_Java 同步块

Java同步块用来标记一个方法或一个代码块为同步的。Java同步块可以用来避免竞态。

Java同步关键字

在 Java 中使用 synchronized 来标记同步块。一个同步块是同步在某些对象上。同一个对象上的所有同步块只能有一个线程执行里面的代码。其他线程试图进入同步块都会被阻塞,直到同步块中的现成离开同步块。

synchronized 可以用来标记 4 种不同的同步块:

实例方法

静态方法

实例方法中的代码块

静态代码中的代码块

这些同步块都同步在不同的对象上。视情况去使用它。

同步的实例方法

public synchronized void add(int value) {

this.count += value;

}

一个同步实例方法是同步在拥有该方法的实例上。同步实例方法中只能有一个线程可以执行里面的方法。如果有多个实例,每个实例只能有一个线程去执行同步实例方法,也就是一个实例一个线程。

同步静态方法

public static synchronized void add(int value) {

count += value;

}

同步静态方法同步在类的类对象上。因为 JVM 中每个类只能有一个类对象。只有一个线程可以执行同一个类中的同步静态方法。

一个类只能有一个线程,不管是执行哪一个同步静态方法。

实例方法中的代码块

有时候,可以不需要把整个方法同步,可以把方法的一部分同步。比如下面的代码:一个不同步的方法中包含同步的代码块

public void add(int value) {

synchronized(this) {

this.count += value;

}

}

上面的示例代码使用同步块构造器来标记代码块是同步的。这个代码执行起来和同步方法一样。

下面的代码执行效果是一样的

public class MyClass {

public synchronized void log1(String msg1, String msg2) {

log.writeln(msg1);

log.writeln(msg2);

}

public viod log2(String msg1, String msg2) {

synchronized(this) {

log.writeln(msg1);

log.writeln(msg2);

}

}

}

如果第二个同步块不是同步在this实例对象上,那么两个方法可以被线程同时执行。

同步静态代码块

public class MyClass {

public static synchronized void log1(String msg1, String msg2) {

log.writeln(msg1);

log.writeln(msg2);

}

public static viod log2(String msg1, String msg2) {

synchronized(MyClass.class) {

log.writeln(msg1);

log.writeln(msg2);

}

}

}

这些方法都同步在类上。

如果第二个同步块不是同步在MyClass.class这个对象上。那么这两个方法可以同时被线程访问。

Java 同步代码例子

public class Counter {

long count = 0;

public synchronized void add(long value) {

this.count += value;

}

}

``java

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

}

}

}

``java

public class Example {

public static void main(String[] args) {

Counter counter = new Counter();

Thread threadA = new CounterThread(counter);

Thread threadB = new CounterThread(counter);

threadA.start();

threadB.start();

}

}

当线程创建的时候,都传入了相同的 Counter 实例。Counter.add() 是同步实例方法。所以每次只能有一个线程可以执行该方法。另外一个线程只能等待它执行完才能去执行方法。

如果两个线程持有的不是同一个 Counter 实例的话,就不会有这个问题。

public class Example {

public static void main(String[] args) {

Counter counterA = new Counter();

Counter counterB = new Counter();

Thread threadA = new CounterThread(counterA);

Thread threadB = new CounterThread(counterB);

threadA.start();

threadB.start();

}

}

QA

Q:

如果一个对象有多个方法加了synchronized,那么该对象有几把锁?

A:

对象锁是在一个类的对象上加的的锁,只有一把,不管有几个方法进行了同步。

这些同步方法都共有一把锁,只要一个线程获得了这个对象锁,其他的线程就不能访问该对象的任何一个同步方法。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值