Java learning-thread synchronization (synchronized): synchronized code blocks, synchronization methods, Lock locks handle thread safety issues

1. Synchronization code block:

Ticket
sales cases attended thread safety issues and sold non-existent and duplicate tickets

Solution 1: Use synchronous code block
Format:

 synchronized(){
    
    
            可能会出现线程安全问题的代码(访问了共享数据的代码)
        }

Note:
1. Through the lock object in the code block, any object can be used.
2. However, it must be ensured that the lock object used by multiple threads is the same. The
lock object functions
to lock the synchronization code block, and only one thread is in the synchronization code. Block execution

[Principle of Synchronization Technology]

Take the three threads in the ticket selling case as an example:
a lock object is used, this lock object is called a synchronization lock, also called an object lock or an object monitor

	3个线程一起抢夺CPU的执行权,谁抢到了谁执行run方法,进行卖票
	t0抢到了CPU的执行权,执行run方法,遇到synchronized代码块
	这时t0会检查synchronized代码块是否有锁对象
	发现有,【就会获取到锁对象,进入到同步中执行】
	
	t1抢到了CPU的执行权,执行run方法,遇到synchronized代码块
	这时t1会检查synchronized代码块是否有锁对象
	【发现没有,t1,就会进入到阻塞状态,会一直等待t0线程归还锁对象,一直到t0线程执行完同步中的代码,会把锁对象归还给同步代码块,t1才能继续获取到锁对象进入到同步中执行】
	
	 t2同理。
	 
由此我们可以得出:【同步中的线程,没有执行完毕不会释放锁,同步外的线程没有锁进不去】

** [Synchronization guarantees that only one thread can execute shared data in synchronization, ensuring safety] ** But because the program frequently judges the lock, acquires the lock, and releases the lock, the efficiency of the program will be reduced.

Code demo :

public class RunnableImpl implements Runnable{
    
    

    //定义一个多线程共享的票源
    private int ticket = 100;

    //创建一个锁对象
   Object lock = new Object();

    //设置线程任务:卖票
    @Override
    public void run() {
    
    
        //使用死循环,让卖票偶重复执行
        while (true) {
    
    
            synchronized (lock) {
    
    
                //先判断票是否存在
                if(ticket > 0) {
    
    
                    //票存在,卖票 ticket--
                    //提高安全问题出现的概率,让程序睡眠
                    try {
    
    
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
    
    
                        e.printStackTrace();
                    }
                    //票存在,卖票 tichet--
                    String name = Thread.currentThread().getName();
                    System.out.println(name + "正在卖第:" + ticket-- +"张票。");
                }
            }
        }
    }
}

Insert picture description here

2. Synchronization method

Synchronization method: The method modified by synchronized is called the synchronization method, which ensures that when the A thread executes the method, other threads can only wait outside the method.
Format:
Steps to use:
1. Take out the code that accesses the shared data and put it in a method
2. Add the synchronized modifier to the method

格式:定义方法的格式
        修饰符 synchronized 发挥值类型 方法名(参数列表) {
    
    
            可能出现线程安全的代码(访问了共享数据的代码)
        }

Synchronization method will also lock the code inside the method and
only allow one thread to execute.
Who is the lock object of the synchronization method is to implement the class object new RunnableImpl(),
which is this

Code demo :

public class RunnableImpl implements Runnable{
    
    

    //定义一个多线程共享的票源
    private int ticket = 100;

    //设置线程任务:卖票
    @Override
    public void run() {
    
    
        while (ticket > 0) {
    
    
           payTicket();
        }
    }
    /*
        定义一个同步方法
        同步方法也会把方法内部的代码锁住
        只让一个线程执行
        同步方法的锁对象是谁,就是实现类对象  new RunnableImpl()
        也就是this
    */
    public synchronized void payTicket() {
    
    
        //先判断票是否存在
        if(ticket > 0) {
    
    
            //票存在,卖票 ticket--
            //提高安全问题出现的概率,让程序睡眠
            try {
    
    
                Thread.sleep(100);
            } catch (InterruptedException e) {
    
    
                e.printStackTrace();
            }
            System.out.println(Thread.currentThread().getName()+ "-->正在,卖第"+ ticket + "张票");
            ticket--;
        }
    }
}

Insert picture description here

Lock

java.util.concurrent.locks.Lock接口
Lock 实现提供了比synchronized方法和语句可获得的更广泛的锁定操作
Lock接口中的方法:
 public void lock() //:加同步锁。
 public void unlock() //:释放同步锁。

[Use steps:]
1. Create a ReentrantLock object at the member location
2. Call the method lock in the Lock interface to obtain the lock before the code
that may have security issues 3. Call the method unlock in the Lock interface after the code that may have security issues Release lock

Program demonstration

public class RunnableImpl implements Runnable{
    
    

    //定义一个多线程共享的票源
    private int ticket = 100;
   // 1.在成员位置创建一个ReentrantLock对象
    Lock lock = new ReentrantLock();
    //设置线程任务:卖票
    @Override
    public void run() {
    
    
        while (true) {
    
    
            //2.在可能会出现安全问题的代码前调用Lock接口中方法lock获取锁
            lock.lock();
            //先判断票是否存在
            if(ticket > 0) {
    
    
                //票存在,卖票 ticket--
                //提高安全问题出现的概率,让程序睡眠
                try {
    
    
                    Thread.sleep(100);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()+ "-->正在,卖第"+ ticket + "张票");
                ticket--;
            }

            //3.在可能会出现安全问题的代码后调用Lock接口中方法unlock释放锁
            lock.unlock();
        }
    }
}

Insert picture description here

Guess you like

Origin blog.csdn.net/weixin_44664432/article/details/106729803