java架构牛逼代码(七爪源码Java中的同步)
java架构牛逼代码(七爪源码Java中的同步)类锁在Java中,每个对象都会有一个监控对象,也就是Java对象的锁,通常称为“内置锁”或“对象锁”。一个类中可以有多个对象,所以每个对象都有自己的对象锁,互不干扰。可见性:必须保证在释放锁之前,对共享变量所做的修改对于后续获取锁的另一个线程是可见的(即在获取锁时应该获取最新的共享变量的值),否则另一个thread 不一致的原因可能是继续对本地缓存的副本进行操作。对象锁和类锁对象锁定
概念
Synchronized是Java中的一个关键字,它使用锁机制来实现同步。
锁定机构具有以下两个特点。
互斥:即只允许一个线程同时持有一个对象锁,该特性用于实现多线程中的协调机制,使得只有一个线程可以对代码块进行同步(复合操作) ) 同时。使用权。互斥也经常被称为操作的原子性。
可见性:必须保证在释放锁之前,对共享变量所做的修改对于后续获取锁的另一个线程是可见的(即在获取锁时应该获取最新的共享变量的值),否则另一个thread 不一致的原因可能是继续对本地缓存的副本进行操作。
对象锁和类锁
对象锁定
在Java中,每个对象都会有一个监控对象,也就是Java对象的锁,通常称为“内置锁”或“对象锁”。一个类中可以有多个对象,所以每个对象都有自己的对象锁,互不干扰。
类锁
在Java中,每个类也有一个锁,可以称为类锁。类锁是通过对象锁实现的,即类的类对象锁。每个类只有一个 Class 对象,因此每个类只有一个类锁。
同步使用分类
同步的使用可以分为两个维度。
1 按修饰对象分类
synchronized 可以装饰方法和代码块。
Decorated code block
- synchronized(this|object) {}
- synchronized(class.class) {}Modification method
- Decorate a non-static method
- Decorate static methods
2 按获取锁分类
Acquire object lock
- synchronized(this|object) {}
- Decorate a non-static methodAcquire class lock
- Synchronized(class.class) {}
- Decorate static methods non-static methods
synchronized的使用详解
这里根据获取锁的分类来分析synchronized的用法。
文章中的所有示例都使用这四个线程。
public class medium01Test{
public static void main(String[] args) {
SyncThread syncThread = new SyncThread();
Thread F_thread1 = new Thread(new SyncThread() "F_thread1");
Thread F_thread2 = new Thread(new SyncThread() "F_thread2");
Thread F_thread3 = new Thread(syncThread "F_thread3");
Thread F_thread4 = new Thread(syncThread "F_thread4");
F_thread1.start();
F_thread2.start();
F_thread3.start();
F_thread4.start();
}
}
1 使用对象锁
该对象是新创建的,与其他对象无关。
class SyncThread implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() "_Sync: " new SimpleDateFormat("HH:mm:ss").format(new Date()));
synchronized (new SyncThread()) {
try {
System.out.println(Thread.currentThread().getName() "_Sync_Start: " new SimpleDateFormat("HH:mm:ss").format(new Date()));
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() "_Sync_End: " new SimpleDateFormat("HH:mm:ss").format(new Date()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
F_thread1_Sync: 23:20:55
F_thread2_Sync: 23:20:55
F_thread4_Sync: 23:20:55
F_thread3_Sync: 23:20:55
F_thread1_Sync_Start: 23:20:55
F_thread2_Sync_Start: 23:20:55
F_thread4_Sync_Start: 23:20:55
F_thread3_Sync_Start: 23:20:55
F_thread4_Sync_End: 23:20:57
F_thread1_Sync_End: 23:20:57
F_thread3_Sync_End: 23:20:57
F_thread2_Sync_End: 23:20:57
四个线程同时开始和结束,因为作为锁的对象和线程属于不同的实例。
2 使用类锁,不管是哪个类,都会被拦截
class SyncThread implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() "_Sync: " new SimpleDateFormat("HH:mm:ss").format(new Date()));
synchronized (SyncThread.class) {
try {
System.out.println(Thread.currentThread().getName() "_Sync_Start: " new SimpleDateFormat("HH:mm:ss").format(new Date()));
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() "_Sync_End: " new SimpleDateFormat("HH:mm:ss").format(new Date()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
F_thread1_Sync: 23:23:11
F_thread2_Sync: 23:23:11
F_thread3_Sync: 23:23:11
F_thread4_Sync: 23:23:11
F_thread1_Sync_Start: 23:23:11
F_thread1_Sync_End: 23:23:13
F_thread4_Sync_Start: 23:23:13
F_thread4_Sync_End: 23:23:15
F_thread3_Sync_Start: 23:23:15
F_thread3_Sync_End: 23:23:17
F_thread2_Sync_Start: 23:23:17
F_thread2_Sync_End: 23:23:19
可以发现,使用类锁一次只能通过一个。
3 使用这个对象锁
class SyncThread implements Runnable {
@Override
public void run() {
System.out.println(Thread.currentThread().getName() "_Sync: " new SimpleDateFormat("HH:mm:ss").format(new Date()));
synchronized (this) {
try {
System.out.println(Thread.currentThread().getName() "_Sync_Start: " new SimpleDateFormat("HH:mm:ss").format(new Date()));
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() "_Sync_End: " new SimpleDateFormat("HH:mm:ss").format(new Date()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
F_thread1_Sync: 23:23:56
F_thread2_Sync: 23:23:56
F_thread3_Sync: 23:23:56
F_thread1_Sync_Start: 23:23:56
F_thread4_Sync: 23:23:56
F_thread2_Sync_Start: 23:23:56
F_thread3_Sync_Start: 23:23:56
F_thread1_Sync_End: 23:23:58
F_thread2_Sync_End: 23:23:58
F_thread3_Sync_End: 23:23:58
F_thread4_Sync_Start: 23:23:58
F_thread4_Sync_End: 23:24:00
线程 1 和 2 同时结束,线程 3 和 4 一个接一个。 原因是 3 和 4 属于同一个实例。
4 使用同步修改方法
作用域是整个方法,所以方法中的所有代码都是同步的。
class SyncThread implements Runnable {
@Override
public void run() {
sync();
}
public synchronized void sync() {
System.out.println(Thread.currentThread().getName() "_Sync: " new SimpleDateFormat("HH:mm:ss").format(new Date()));
try {
System.out.println(Thread.currentThread().getName() "_Sync_Start: " new SimpleDateFormat("HH:mm:ss").format(new Date()));
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() "_Sync_End: " new SimpleDateFormat("HH:mm:ss").format(new Date()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
F_thread2_Sync: 23:26:38
F_thread3_Sync: 23:26:38
F_thread2_Sync_Start: 23:26:38
F_thread3_Sync_Start: 23:26:38
F_thread1_Sync: 23:26:38
F_thread1_Sync_Start: 23:26:38
F_thread3_Sync_End: 23:26:40
F_thread2_Sync_End: 23:26:40
F_thread1_Sync_End: 23:26:40
F_thread4_Sync: 23:26:40
F_thread4_Sync_Start: 23:26:40
F_thread4_Sync_End: 23:26:42
对于非静态方法,会拦截同一个实例的线程访问,可以同时访问不同的实例。 也就是此时默认的对象锁(this)。
class SyncThread implements Runnable {
@Override
public void run() {
sync();
}
public synchronized static void sync() {
System.out.println(Thread.currentThread().getName() "_Sync: " new SimpleDateFormat("HH:mm:ss").format(new Date()));
try {
System.out.println(Thread.currentThread().getName() "_Sync_Start: " new SimpleDateFormat("HH:mm:ss").format(new Date()));
Thread.sleep(2000);
System.out.println(Thread.currentThread().getName() "_Sync_End: " new SimpleDateFormat("HH:mm:ss").format(new Date()));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
F_thread1_Sync: 23:28:47
F_thread1_Sync_Start: 23:28:47
F_thread1_Sync_End: 23:28:49
F_thread4_Sync: 23:28:49
F_thread4_Sync_Start: 23:28:49
F_thread4_Sync_End: 23:28:51
F_thread3_Sync: 23:28:51
F_thread3_Sync_Start: 23:28:51
F_thread3_Sync_End: 23:28:53
F_thread2_Sync: 23:28:53
F_thread2_Sync_Start: 23:28:53
F_thread2_Sync_End: 23:28:55
静态方法默认类锁。
结论
- 对于静态方法,由于此时还没有生成对象,所以只能使用类锁。
- 只要使用类锁,所有线程都会被拦截,只能访问一个线程。
- 对于对象锁(this),如果是同一个实例,会顺序访问,如果是不同的实例,可以同时访问。
- 如果对象锁与被访问的对象无关,则两者会同时被访问。
关注七爪网,获取更多APP/小程序/网站源码资源!