您现在的位置是:主页 > news > 苏州软件开发公司/百度seo指数查询
苏州软件开发公司/百度seo指数查询
admin2025/5/17 6:37:30【news】
简介苏州软件开发公司,百度seo指数查询,好医生网站怎么做不了题目了,网站多久需要维护文章目录前言synchronized 关键字synchronized 和字节码对象和内置锁(监视器锁)synchronized 需要借助于一个对象synchronized 修饰的方法可以重入synchronized 的锁解除synchronized 内置锁的公平性synchronized 使用举例没有 synchronized 同步的例子使…
文章目录
- 前言
- synchronized 关键字
- synchronized 和字节码
- 对象和内置锁(监视器锁)
- synchronized 需要借助于一个对象
- synchronized 修饰的方法可以重入
- synchronized 的锁解除
- synchronized 内置锁的公平性
- synchronized 使用举例
- 没有 synchronized 同步的例子
- 使用 synchronized 修饰静态方法
- 使用 synchronized 修饰代码块
- synchronized(this)的正确和错误举例
- 正确用法:所有线程共享同一个对象
- 错误用法:每个线程传入一个新对象
- 参考资料
前言
体能状态先于精神状态,习惯先于决心,聚焦先于喜好。
synchronized 关键字
Java 提供了一种内置的锁机制来支持原子性:同步代码块(Synchronized Block).
使用 synchronized 关键字修饰一个方法,或者在一个方法里修饰一个代码块。
synchronized 和字节码
synchronized 关键字在编译之后会被体现在字节码中,其对应两个字节码 monitorenter和 monitorexit,而这两个字节码分别对应了Java内存模型中的 8个基本命令的 lock 和 unlock 命令。lock命令会锁定主内存中涉及到的变量,unlock则会解锁,锁定之后,其他线程无法操作与该对象内置锁相关的代码块或方法的代码,同时也无法从主内存同步涉及到的变量值,unlock命令执行前,当前线程会将工作内存的相关变量同步到主内存。
对象和内置锁(监视器锁)
每个Java对象都可以用做一个实现同步的锁,这些锁被称为内置锁(Intrinsic Lock)或监视器锁(Monitor Lock).
当 synchronized 修饰一个方法时,那么其所以来的对象就是当前类的对象,只有通过这个对象调用该方法才可以同步不同的线程,当这个方法是static修饰的静态方法时,所有调用该方法的线程都将实现同步。
当synchronized 修饰一个方法中的代码块时需要明确指定一个对象,可以是单独声明的一个对象,也可以是 “this”表示本类,对于单独声明的对象来说,其如果被static 修饰,那么这个代码块可以启动同步任何调用该代码块的线程的作用,否则,其只能作用于拥有对应对象的线程的作用。
synchronized 需要借助于一个对象
synchronized 需要借助于一个Java 对象来获得内置锁。当这个对象被多个线程共享的时候,相关的线程在这个代码块是同步的。
所以务必注意,synchronized 修饰的方法或者代码块涉及的对象是否有被不同的线程关联到。一般而言,使用static 修饰的方法或者全局变量可以确保关联到同一个对象。
synchronized 修饰的方法可以重入
这个概念是和重入锁的概念比较的
你可以在一个 synchronized 修饰的方法中调用另一个 synchronized 修饰的方法,程序不会出现问题。
synchronized 的锁解除
一种是代码运行结束,unlock了,内置锁解除。
另一种是抛出异常,锁也会解除。
再一种是 Object.wait()方法,线程会释放锁,但是同时会等待其他线程Object.notify(),这种释放如果没有唤醒会造成线程永久阻塞。
但是没有其他主动解除锁的机制,比如锁中断机制——彻底的接触锁,而不是先释放然后再次尝试获取。
synchronized 内置锁的公平性
无法保证线程获得锁的公平性,也无法保证线程优先级。
synchronized 使用举例
我们将使用线程池做几个不同的实验,感受不使用同步、使用不同方式的同步所带来的不同的效果。
没有 synchronized 同步的例子
可以从运行结果看到,结果是无序的,每个方法打印开始和结束是混杂在一起的。
- 代码
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class SynchronizedTest {private final static Object obj=new Object();/*** 使用 synchronized 修饰整个方法体** @param name*/public static void blockMethod(String name){System.out.println(name+" begin :"+System.currentTimeMillis());try {Random random=new Random();Thread.sleep(random.nextInt(1000));}catch(InterruptedException e){System.out.println("exception msg:"+e);}System.out.println(name+" end :"+System.currentTimeMillis());}/*** 一个内部类写一个线程*/static class MyThread extends Thread{public MyThread(){}public MyThread(String name){this.name=name;}private String name;@Overridepublic void run() {//调用 synchronized 修饰的方法blockMethod(name);}}/**** @param args*/public static void main(String [] args){ExecutorService pool=Executors.newFixedThreadPool(3);try{for (int i=0;i<3;i++){MyThread m=new MyThread("thread"+i);pool.submit(m);}}finally{pool.shutdown();}}
}
- 输出结果:每个线程的开始和结束混杂在一起
thread1 begin :1564148430029
thread0 begin :1564148430032
thread2 begin :1564148430033
thread1 end :1564148430275
thread0 end :1564148430730
thread2 end :1564148430730
使用 synchronized 修饰静态方法
- 代码
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class SynchronizedTest {private final static Object obj=new Object();/*** 使用 synchronized 修饰整个方法体** @param name*/public static synchronized void blockMethod(String name){System.out.println(name+" begin :"+System.currentTimeMillis());try {Random random=new Random();Thread.sleep(random.nextInt(1000));}catch(InterruptedException e){System.out.println("exception msg:"+e);}System.out.println(name+" end :"+System.currentTimeMillis());}/*** 一个内部类写一个线程*/static class MyThread extends Thread{public MyThread(){}public MyThread(String name){this.name=name;}private String name;@Overridepublic void run() {//调用 synchronized 修饰的方法blockMethod(name);}}/*** @param args*/public static void main(String [] args){ExecutorService pool=Executors.newFixedThreadPool(3);try{for (int i=0;i<3;i++){MyThread m=new MyThread("thread"+i);pool.submit(m);}}finally{pool.shutdown();}}
}
- 输出结果:每个线程的开始和结束是连接在一起的
thread1 begin :1564148603370
thread1 end :1564148603813
thread2 begin :1564148603813
thread2 end :1564148603941
thread0 begin :1564148603941
thread0 end :1564148604358
使用 synchronized 修饰代码块
这里使用全局静态对象作为内置锁对象,所以含synchronized 代码块的方法也必须是静态的。
- 代码
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class SynchronizedTest {private final static Object obj=new Object();/*** 使用 synchronized 修饰方法体** @param name*/public static void blockMethod(String name){synchronized (obj){System.out.println(name+" begin :"+System.currentTimeMillis());try {Random random=new Random();Thread.sleep(random.nextInt(1000));}catch(InterruptedException e){System.out.println("exception msg:"+e);}System.out.println(name+" end :"+System.currentTimeMillis());}}/*** 一个内部类写一个线程*/static class MyThread extends Thread{public MyThread(){}public MyThread(String name){this.name=name;}private String name;@Overridepublic void run() {blockMethod(name);}}/*** 你可以尝试去除 blockMethod() 方法中 synchronized 后运行main方法,看看有什么不同* @param args*/public static void main(String [] args){ExecutorService pool=Executors.newFixedThreadPool(3);try{for (int i=0;i<3;i++){MyThread m=new MyThread("thread"+i);pool.submit(m);}}finally{pool.shutdown();}}
}
- 结果
thread1 begin :1564151473516
thread1 end :1564151473625
thread2 begin :1564151473631
thread2 end :1564151473692
thread0 begin :1564151473693
thread0 end :1564151474385
synchronized(this)的正确和错误举例
使用 synchronized(this) 表示直接使用 该代码块所在方法对应的对象作为内置所对象。
这样一般需要我们将内置锁对象通过线程的构造方法传递给线程。如果多个线程传递进去的是同一个对象,那么万事大吉,否则不同对象会因为对象不同而持有不同的内置锁,从而不再同步——线程不安全了。
正确用法:所有线程共享同一个对象
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class SynchronizedTest {private final static Object obj=new Object();/*** 使用 synchronized 修饰方法体** @param name*/public void blockMethod(String name){synchronized (this){System.out.println(name+" begin :"+System.currentTimeMillis());try {Random random=new Random();Thread.sleep(random.nextInt(1000));}catch(InterruptedException e){System.out.println("exception msg:"+e);}System.out.println(name+" end :"+System.currentTimeMillis());}}/*** @param args*/public static void main(String [] args){ExecutorService pool=Executors.newFixedThreadPool(3);try{//只创建一个对象SynchronizedTest s=new SynchronizedTest();for (int i=0;i<3;i++){MyThread m=new MyThread("thread"+i,s);pool.submit(m);}}finally{pool.shutdown();}}
}/*** 一个内部类写一个线程*/
class MyThread extends Thread{private String name;private SynchronizedTest s;public MyThread(){}public MyThread(String name,SynchronizedTest s){this.name=name;this.s=s;}@Overridepublic void run() {s.blockMethod(name);}
}
- 结果
thread1 begin :1564153234192
thread1 end :1564153234459
thread2 begin :1564153234459
thread2 end :1564153235232
thread0 begin :1564153235232
thread0 end :1564153236279
错误用法:每个线程传入一个新对象
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class SynchronizedTest {private final static Object obj=new Object();/*** 使用 synchronized 修饰方法体** @param name*/public void blockMethod(String name){synchronized (this){System.out.println(name+" begin :"+System.currentTimeMillis());try {Random random=new Random();Thread.sleep(random.nextInt(1000));}catch(InterruptedException e){System.out.println("exception msg:"+e);}System.out.println(name+" end :"+System.currentTimeMillis());}}/*** @param args*/public static void main(String [] args){ExecutorService pool=Executors.newFixedThreadPool(3);try{for (int i=0;i<3;i++){//每个线程传入一个新对象SynchronizedTest s=new SynchronizedTest();MyThread m=new MyThread("thread"+i,s);pool.submit(m);}}finally{pool.shutdown();}}
}/*** 一个内部类写一个线程*/
class MyThread extends Thread{private String name;private SynchronizedTest s;public MyThread(){}public MyThread(String name,SynchronizedTest s){this.name=name;this.s=s;}@Overridepublic void run() {s.blockMethod(name);}
}
- 结果
thread1 begin :1564152677663
thread0 begin :1564152677665
thread2 begin :1564152677665
thread2 end :1564152678085
thread1 end :1564152678284
thread0 end :1564152678376
参考资料
[1]、Java 并发编程实战
[2]、Java 高并发程序设计
[3]、深入理解 Java 虚拟机