同步锁 java_java之同步锁---synchronized

本文详细解析了Java中`synchronized`关键字在代码块、静态方法和非静态方法中的应用,通过实例演示了如何确保线程同步,以及不同场景下synchronized锁对象的区别。重点讨论了synchronized(this)、静态变量和类对象的同步效果。
摘要由CSDN通过智能技术生成

1.背景

前几天线上项目出现一个问题,由于并发问题,导致服务器集群中的部分服务器中的数据没有更新。经过review代码,发现没有进行数据的同步操作。最后使用synchronize解决了问题。解决问题后,在空余时间对synchronized的应用进行了研究。

2.synchronized介绍

synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:

1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;

2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;

3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;

4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

3. 示例

3.1 synchronized修饰代码块

如果多个线程访问的是同一个实例对象,则会出现等待,如果多个线程访问的都是不同的实例对象,则不会出现等待

3.1.1 synchronized(this)

代码如下:

public class SyncBlock implementsRunnable{

private static Integercount;

publicSyncBlock() {

// TODO Auto-generated constructor stub

count = 0;

}

public intgetCount(){

returncount;

}

@Override

public voidrun() {

// TODO Auto-generated method stub

System.out.println("当前执行的程序:"+Thread.currentThread().getName());

synchronized(this) {

for (int i = 0; i < 5; i++) {

try{

System.out.println(Thread.currentThread().getName() + ":" + (count++));

Thread.sleep(100);

} catch(InterruptedException e) {

e.printStackTrace();

}

}

}

}

public static voidmain(String[] args){

SyncBlock syncBlock = newSyncBlock();

Thread th1 = new Thread(syncBlock,"第一集团军");

Thread th2 = new Thread(syncBlock,"第二集团军");

th1.start();

th2.start();

}

}

执行结果如下:

b9a6940528ff93f051142c20518e60a4.png

通过执行结果可以看出,同步锁机制生效。synchronized(this)使得两个线程同步等待。在main函数中增加三行代码

public static void main(String[] args){

SyncBlock syncBlock = new SyncBlock();

SyncBlock syncBlock3 = new SyncBlock();

Thread th1 = new Thread(syncBlock,"第一集团军");

Thread th2 = new Thread(syncBlock,"第二集团军");

Thread th3 = new Thread(syncBlock3,"第三集团军");

th1.start();

th2.start();

th3.start();

}

执行结果如下:

73ee8cfb870bf156562581a6b64b6570.png

通过执行结果可以看出,线程1和线程2之间出现了等待,线程1执行完之后执行线程2,而线程3与线程1和2之间没有等待。这是因为线程1和线程2是监视的同一个SyncBlock对象syncBlock,而线程3监视的是独立的对象syncBlock3。也就是说,synchronized(this)对于线程3与线程1和2,锁的是不同对象,所以彼此之间无法同步。

3.1.2 静态变量synchronized(this.count)

锁的对象是整型的实例对象count,如果count对象值是固定不变的,则所有线程之间都会等待,如果count是变化的,如count++,则所有线程之间都不会等待。因为count++的结果会改变count的对象引用,所以

synchronized(count)锁定的是不同的实例对象,也就没有起到锁的作用。

修改上面的代码如下:

1 public voidrun() {2 //TODO Auto-generated method stub

3 System.out.println("当前执行的程序:"+Thread.currentThread().getName());4 synchronized(count) {5 for (int i = 0; i < 5; i++) {6 try{7 System.out.println(Thread.currentThread().getName() + ":" + (count++));8 Thread.sleep(100);9 } catch(InterruptedException e) {10 e.printStackTrace();11 }12 }13 }14 }

执行结果如下:

405d1c56ebe12d83cf1a0b53082c24fa.png

如果count的值不发生改变

1 public voidrun() {2 //TODO Auto-generated method stub

3 System.out.println("当前执行的程序:"+Thread.currentThread().getName());4 synchronized(count) {5 for (int i = 0; i < 5; i++) {6 try{7 System.out.println(Thread.currentThread().getName() + ":" +(count));8 Thread.sleep(100);9 } catch(InterruptedException e) {10 e.printStackTrace();11 }12 }13 }14 }

执行结果如下:由于count值不发生变化,count是对多有实例对象共享,所以所有线程多会出现等待。

bdb1e67a122f2e9a12df8092425e6309.png

3.1.3  synchronized(A.class)

A.class表示类对象。每个类都对应着一个这样的类对象,所有线程都会彼此间等待。

修改代码如下:

1 public voidrun() {2 //TODO Auto-generated method stub

3 System.out.println("当前执行的程序:"+Thread.currentThread().getName());4 synchronized(SyncBlock.class) {5 for (int i = 0; i < 5; i++) {6 try{7 System.out.println(Thread.currentThread().getName() + ":" + (count++));8 Thread.sleep(100);9 } catch(InterruptedException e) {10 e.printStackTrace();11 }12 }13 }14 }

执行结果如下:

a9b19b53f5e9af6e06f0af378f662d1e.png

3.2 synchronized非静态方法

1 synchronized public voidrun() {2 //TODO Auto-generated method stub

3 System.out.println("当前执行的程序:"+Thread.currentThread().getName());5 for (int i = 0; i < 5; i++) {6 try{7 System.out.println(Thread.currentThread().getName() + ":" + (count++));8 Thread.sleep(100);9 } catch(InterruptedException e) {10 e.printStackTrace();11 }12 }14 }

执行结果如下,与在方法在使用synchronized(this)相同。多个线程访问的是同一个实例对象,则会出现等待,如果多个线程访问的都是不同的实例对象,则不会出现等待

177d2ba229736fee0f25a9a800480a31.png

3.4 synchronized静态方法

静态方法属于类方法,不属于任一实例对象。为所有实例对象所共享。因此对于所有线程调用synchronized静态方法,彼此之间会出现等待。与synchronized(A.clsss)类似。只是作用范围不同。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值