synchronized用法解析

it2024-03-15  56

synchronized详解

使用同步代码块synchronized (this) {}--对象锁Object obj = new Object(); synchronized(obj){...} 对象锁synchronized(.class){...} 类锁,锁的是这个类。 修饰实例方法 对象锁修饰静态方法 类锁测试代码

多个线程执行对同一个Java对象访问时候,为了保证数据的有效性,通常会使用synchronized关键字,俗称多线程安全。

synchronized从语法上一共有三种语法,修饰静态方法,修饰实例方法,在方法中使用代码块。

从锁住的对象来看两种:锁住类和和实例对象。

锁住实例对象:无论多少个线程使用同一个实例对象,都需要排队。但是多个线程使用多个对象,就不用排队了。

锁住类:无论多少个对象,只要对象都是一个类,多个线程使用多个对象,依旧要排队。

注意:一定要检查对象是不是实例对象,局部/静态变量是无法锁住的。


使用同步代码块

synchronized (this) {}–对象锁

public void m1(){ synchronized (this) {//这里的this锁住的是所在类的实例对象对象 ...................; } } //因为是对象锁。两个线程使用两个对象。就锁不住了。

Object obj = new Object(); synchronized(obj){…} 对象锁

Object lock1=new Object();//实例对象,不能是局部变量 public void m1(){// synchronized (lock1){//这里的锁住的是lock1,本质锁住的是所在类的实例对象。 ...................; } } //因为是对象锁,两个线程使用两个对象,就锁不住了。

synchronized(.class){…} 类锁,锁的是这个类。

public void m1(){ synchronized (xxx.class) {//这里锁住的是xxx类。 ...................; } } //因为是类锁。只要对象是这个xxx类的,无论几个线程使用几个个对象。都可以锁。

修饰实例方法 对象锁

//修饰实例方法,本质还是对象锁。 public synchronized void m1(){ } //多个线程使用多个对象,无法被锁。

修饰静态方法 类锁

//修饰静态方法,类锁。只要对象是这个类的,无论多少个对象,都会被锁。 public synchronized static void m1(){ }

测试代码

上述例子,可以用以下代码进行简单测试。

public class work01 { public static void main(String[] args) throws InterruptedException { MyThread myThread=new MyThread();//同一个对象 Thread t1=new Thread(myThread,"t1");Thread t2=new Thread(myThread,"t2"); t1.start();t2.start(); } } class MyThread extends Thread{ count c=new count();//必须是实例对象 public void run(){ c.m1(); } } class count{ public void m1(){ synchronized (this){ for (int i = 0; i <30 ;i++) { System.out.println(Thread.currentThread().getName() + "-->" + i); } } } }

总结:

无论synchronized关键字加在方法上还是对象上,如果它作用的对象是非静态的,则它取得的锁是对象;如果synchronized作用的对象是一个静态方法或一个类,则它取得的锁是类,该类所有的对象同一把锁。实现同步是要很大的系统开销作为代价的,可能造成死锁,所以尽量避免无谓的同步控制。优先使用局部变量,局部变量在栈区,是不共享的,静态变量在方法区中,实例变量在堆中,堆和方法区都是共享的。
最新回复(0)