Interview questions-13 lock

First of all, let's talk about the difference between synchronize and Lock

Both are locks, used to control concurrency conflicts. The difference is that Lock is an interface that provides more functions. In addition to this, they have the following differences:
synchronize automatically releases the lock, while Lock must be manually released, and there is an exception in the code It will cause the unlock code to not be executed, so the Lock is generally released in Finally, and the synchronize release of the lock is automatically executed by the JVM.
Lock has the concept of a shared lock, so you can set read-write locks to improve efficiency, but synchronize cannot. (Both are reentrant)
Lock allows the thread to respond to interrupts in the process of acquiring the lock, while synchronize does not, the thread will wait forever. The lock.lockInterruptibly() method will give priority to responding to interrupts, instead of first obtaining locks like lock.
Lock locks code blocks, and synchronize can also lock methods and classes.

Two, synconized realization principle

1. JVM implements method synchronization and code block synchronization based on entering and exiting the Monitor object.
Method-level synchronization is implicit, that is, it does not need to be controlled by bytecode instructions. It is implemented in method call and return operations. The JVM can
distinguish whether a method is a synchronized method from the ACC_SYNCHRONIZED access flag in the method_info Structure in the method constant pool . When the method is called, the calling instruction will check
whether the ACC_SYNCHRONIZED access flag of the method is set. If it is set, the execution thread will first hold the monitor (the term monitor is used in the virtual machine specification),
and then execute the method, and finally The monitor is released when the method is completed (whether it is completed normally or abnormally).
2. The synchronization of the code block uses the two bytecode instructions of monitorenter and monitorexit. They are located at the beginning and end of the synchronization code block, respectively. When the jvm executes the monitorenter instruction, the current thread tries to acquire the ownership of the monitor object. If the lock is not locked or is already held by the current thread, the lock counter is set to +1; when the monitorexit instruction is executed, the lock counter is -1; When the lock counter is 0, the lock is released. If the acquisition of the monitor object fails, the thread will enter a blocked state until other threads release the lock.
Understanding of various locks

1. Fair lock and unfair lock Fair lock: Very fair, you cannot jump in the queue, you must come first! Unfair lock: Very unfair, you can jump in the queue (the default is unfair) 2. Reentrant locks
Reentrant locks (recursive locks)
Insert picture description here

Synchronized
package com.kuang.lock;
import javax.sound.midi.Soundbank;
// Synchronized
public class Demo01 {
    
    
public static void main(String[] args) {
    
    
Phone phone = new Phone();
new Thread(()->{
    
    
phone.sms();
},"A").start();
new Thread(()->{
    
    
phone.sms();
},"B").start();
}
}
class Phone{
    
    
public synchronized void sms(){
    
    
System.out.println(Thread.currentThread().getName() + "sms");
call(); // 这里也有锁
}
public synchronized void call(){
    
    
System.out.println(Thread.currentThread().getName() + "call");
}
}
Lock 版
package com.kuang.lock;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class Demo02 {
    
    
public static void main(String[] args) {
    
    
Phone2 phone = new Phone2();
new Thread(()->{
    
    
phone.sms();
},"A").start();
new Thread(()->{
    
    
phone.sms();
},"B").start();
}
}
class Phone2{
    
    
Lock lock = new ReentrantLock();
public void sms(){
    
    
lock.lock(); // 细节问题:lock.lock(); lock.unlock(); // lock 锁必须配对,否
则就会死在里面
lock.lock();
try {
    
    
System.out.println(Thread.currentThread().getName() + "sms");
call(); // 这里也有锁
} catch (Exception e) {
    
    
e.printStackTrace();
} finally {
    
    
lock.unlock();
lock.unlock();
}
}
public void call(){
    
    
lock.lock();
try {
    
    
System.out.println(Thread.currentThread().getName() + "call");
} catch (Exception e) {
    
    
e.printStackTrace();
} finally {
    
    
lock.unlock();
}
}
}

3.
Spinlock
Insert picture description here

We customize a lock test
test

package com.kuang.lock;
import java.util.concurrent.atomic.AtomicReference;
* 自旋锁
*/
public class SpinlockDemo {
    
    
// int 0
// Thread null
AtomicReference<Thread> atomicReference = new AtomicReference<>();

// 加锁
public void myLock() {
    
    
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName() + "==> mylock");
// 自旋锁
while (!atomicReference.compareAndSet(null, thread)) {
    
    
}
}

// 解锁
// 加锁
public void myUnLock() {
    
    
Thread thread = Thread.currentThread();
System.out.println(Thread.currentThread().getName() + "==> myUnlock");
atomicReference.compareAndSet(thread, null);
}
}
/**
* 锁
*/
public class asdf {
    
    
public static void main(String[] args) {
    
    
//如果用的是同一个锁 谁先获得锁 谁先用 其他线程只能等待获得锁才能向下走
Lock lock = new ReentrantLock();
// Lock lock1 = new ReentrantLock();
new Thread(()->{
    
    
lock.lock();
try {
    
    
TimeUnit.SECONDS.sleep(5);
System.out.println(Thread.currentThread().getName());
} catch (Exception e) {
    
    
e.printStackTrace();
} finally {
    
    
lock.unlock();
System.out.println("22");
}

},"t1").start();

new Thread(()->{
    
    
lock.lock();
try {
    
    
System.out.println(Thread.currentThread().getName());
} catch (Exception e) {
    
    
e.printStackTrace();
} finally {
    
    
lock.unlock();
System.out.println("33");
}

},"t2").start();
}
}
//运行结果
//t1
//t2
//33
//22

4. Deadlock
Insert picture description here

死锁测试,怎么排除死锁:
public class test1 {
    
    
public static void main(String[] args) {
    
    
String lockA = "A锁";
String lockB = "B锁";
new Thread(new MyThread(lockA,lockB)).start();
new Thread(new MyThread(lockB,lockA)).start();
}
}

class MyThread implements Runnable{
    
    
private String lockA;
private String lockB;

public MyThread(String lockA, String lockB) {
    
    
this.lockA = lockA;
this.lockB = lockB;
}

@Override
public void run() {
    
    
synchronized (lockA){
    
    
System.out.println(Thread.currentThread().getName()+lockA+"get->"+lockB);
try {
    
    
TimeUnit.SECONDS.sleep(2);
} catch (InterruptedException e) {
    
    
e.printStackTrace();
}
synchronized (lockB){
    
    
System.out.println(Thread.currentThread().getName()+lockB+"get->"+lockA);
}
}
}
}

Solve the problem 1. Use jps -l to locate the process number

2. Use jstack + process number to find the deadlock problem

Interview, at work! Troubleshooting: 1. Log 9 2. Stack 1

Guess you like

Origin blog.csdn.net/zyf_fly66/article/details/114085724