Java基础 --- 线程同步 synchronized关键字

synchronized 关键字

  • Lock and Condition interface给了程序员很高的自由度来控制锁, 但是通常不需要这么高的自由度
  • Java提供一套更简便的机制来加锁 ---- synchronized 关键字 和 intrinsic lock
  • Java 1.0之后, 每个object类都有一个 intrinsic lock, 每个object类都有wiat和notifyAll方法

synchronized

  • 当一个方法使用synchronized修饰时, 锁会保护整个方法
  • 也就是如果要执行这个方法, 线程必须拿到intrinsic object lock.

使用synchronized重写transfer方法:

class Bank
{
    
    
	 private double[] accounts;
	 public synchronized void transfer(int from, int to, int amount) throws InterruptedException {
    
    
		 while (accounts[from] < amount)
			wait(); // wait on intrinsic object lock's single condition
		 accounts[from] -= amount;
		 accounts[to] += amount;
		 notifyAll(); // notify all threads waiting on the condition
	 }
	 public synchronized double getTotalBalance() {
    
     . . . }
}

The intrinsic locks and conditions have some limitations. Among them:

  • You cannot interrupt a thread that is trying to acquire a lock.
  • You cannot specify a timeout when trying to acquire a lock.
  • Having a single condition per lock can be inefficient

synchronized 关键字修饰静态方法

  • synchronized 关键字可以修饰静态方法, 也就是对 类 加锁, 也叫做类锁
public class Car {
    
    

    public static synchronized void staticRuning1(Thread thread){
    
    
        System.out.println(thread.getName()+ " static car1 得到锁");
        System.out.println("------ static car1 is running ------");
        working();
        System.out.println(thread.getName()+ " static car1 释放锁");
        System.out.println();
    }
    public static synchronized void staticRuning2(Thread thread){
    
    
        System.out.println(thread.getName()+ " static car2 得到锁");
        System.out.println("------ static car2 is running ------");
        working();
        System.out.println(thread.getName()+ " static car2 释放锁");
        System.out.println();
    }

	public static void  working(){
    
    
        try{
    
    
            Thread.sleep(1000);
        }catch(InterruptedException e){
    
    
            e.printStackTrace();
        }
    }
}

public class test02 {
    
    
    public static void main(String[] args) {
    
    

        //线程1 类
        Thread t1 = new Thread(){
    
    
            @Override
            public void run() {
    
    
                Car.staticRuning1(Thread.currentThread()); //同步类方法1
            }
        };
        t1.start();

        //线程2 类
        Thread t2 = new Thread(){
    
    
            @Override
            public void run() {
    
    
                Car.staticRuning2(Thread.currentThread()); //同步类方法2
            }
        };
        t2.start();
    }
}

Car类不能同时访问两个静态方法

在这里插入图片描述

synchronized代码块 — synchronized blocks

  • 另一种使用 intrinsic lock的方法是使用synchronized代码块
public void transfer(int from, int to, int amount)
 {
    
    
	synchronized (lock) // an ad-hoc lock
	{
    
    
	 accounts[from] -= amount;
	 accounts[to] += amount;
	}
	 System.out.println(. . .);
}

synchronized 保证原子性, 可见性, 有序性

  • 原子性: synchronized 关键字。锁操作,基于 monitorenter 和 monitorexit 字节码指令,保证同步块只有单一线程执行。
  • 可见性: synchronized 等锁机制。同步块的可见性是由“对一个变量执行 unlock 操作之前,必须先把此变量同步回主内存中(执行 store、write 操作)”这条规则获得的。
  • 有序性: synchronized 等锁机制,同步块的有序性是由“一个变量在同一个时刻只允许一条线程对其进行 lock 操作”这条规则获得的。

猜你喜欢

转载自blog.csdn.net/weixin_38803409/article/details/126205158