java synchronized关键字
来源:互联网 发布:百度云域名注册免费 编辑:程序博客网 时间:2024/06/09 13:40
synchronized关键字用于多线程同步,其具有以下作用:
1. 确保线程互斥的访问同步代码
2. 保证共享变量的修改能够及时可见
3. 有效解决重排序问题
其主要有三种用法:
1. 修饰普通方法
2. 修饰静态方法
3. 修饰代码块
测试代码:
public class C{ private static ArrayList<Integer> list=new ArrayList<>(); public void noSyn() { for(int i=0;i<5;++i){ System.out.println(Thread.currentThread().getName()+" "+"no Syn"); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } public synchronized void normalSyn1() { for(int i=0;i<5;++i){ System.out.println(Thread.currentThread().getName()+" "+"normal Syn1 "); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } public static void noSynStatic() { for(int i=0;i<5;++i){ System.out.println(Thread.currentThread().getName()+" "+"no Syn static"); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } public static synchronized void staticSyn() { for(int i=0;i<5;++i){ //list.add(i); System.out.println(Thread.currentThread().getName()+" "+"static syn "+list); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } public void staticString1(){ synchronized (list) { for(int i=0;i<5;++i){ list=new ArrayList<>(); System.out.println(Thread.currentThread().getName()+" "+"static integer1 "+list); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } } public void staticString2(){ synchronized (list) { for(int i=0;i<5;++i){ System.out.println(Thread.currentThread().getName()+" "+"static integer2 "+list); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } } } public synchronized void normalSyn2() { for(int i=0;i<5;++i){ System.out.println(Thread.currentThread().getName()+" "+"normal Syn2"); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } }}
其特点如下:
1.synchronized修饰普通方法methodA时,在不同线程中使用同一对象调用方法methodA,这样会导致先获取该对象锁的线程先执行,其他线程受阻塞。
public static void main(String []ags) throws Exception{ final C c=new C(); final C c1=new C(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.normalSyn(); } }).start(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.normalSyn(); } }).start(); }
2.synchronized修饰普通方法methodA、methodB时,在不同线程中使用同一对象。在线程A中调用methodA,在线程B中调用methodB,这样会导致先获取对象锁的线程先执行,其他线程受阻塞。这表明,synchronized修饰普通方式时,锁住的是对象。当某一个线程获取到该对象锁时,其他线程就不能执行需要该对象锁的方法(即synchronized修饰的普通方法,代码块上为this的synchronized代码块)
public static void main(String []ags) throws Exception{ final C c=new C(); final C c1=new C(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.normalSyn1(); } }).start(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.normalSyn2(); } }).start(); }
结果:
3.synchronized修饰普通方法methodA时,在不同线程中使用不同对象调用该方法,这样会导致各线程按CPU调度进行,没有发送阻塞。这表明,不同对象有不同的对象锁,互不影响。
public static void main(String []ags) throws Exception{ final C c=new C(); final C c1=new C(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.normalSyn1(); } }).start(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c1.normalSyn1(); } }).start();
结果:
4.synchronized修饰普通方法methodA时,在不同线程中同一对象,在线程A中调用methodA,在线程B中调用非synchronized的方法methodB,这样会导致各线程按CPU调度进行,没有发送阻塞。这表明,没有锁的方法不会受到对象锁影响。
public static void main(String []ags) throws Exception{ final C c=new C(); final C c1=new C(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.normalSyn1(); } }).start(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.noSyn(); } }).start(); }
结果:
5.synchronized修饰静态方法时,在不同线程中使用该类的不同对象调用该方法时,这样会导致先获取类锁的线程先执行,其他线程阻塞。
public static void main(String []ags) throws Exception{ final C c=new C(); final C c1=new C(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.staticSyn(); } }).start(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c1.staticSyn(); } }).start(); }
结果:
6.synchronized修饰普通方法methodA、静态方法methodB时,在不同线程中使用同一对象。在线程A中调用methodA,在线程B中调用methodB,这样会导致线程按CPU调度进行,各不影响。因为普通方法锁的是对象,静态方法锁的是类,两者互不干扰。
public static void main(String []ags) throws Exception{ final C c=new C(); final C c1=new C(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.staticSyn(); } }).start(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.normalSyn1(); } }).start(); }
结果:
7.在方法methodA中用synchronized修饰代码块上的静态变量,synchronized修饰静态方法methodB,在不同线程中使用同一对象。在线程A中调用methodA,在线程B中调用methodB,这样会导致线程按CPU调度进行,各不影响。这表明虽然synchronized修饰的是静态变量,但它锁的是该变量;而synchronized修饰静态方式锁的是类,这样它们还是会互不影响。所以在synchronized锁变量时,必须要注意其在其他方法中的控制。
C类中方法staticSyn有所改变:
public static synchronized void staticSyn() { for(int i=0;i<5;++i){ System.out.println(Thread.currentThread().getName()+" "+"static syn "+list); try { Thread.sleep(2000); } catch (InterruptedException e) { // TODO 自动生成的 catch 块 e.printStackTrace(); } } }
public static void main(String []ags) throws Exception{ final C c=new C(); final C c1=new C(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.staticString2(); } }).start(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.staticSyn(); } }).start(); }
结果:
8.在方法methodA中用synchronized修饰代码块上的静态变量,在方法methodB中用synchronized修饰代码块上的同样的静态变量,在不同线程中使用同一对象。在线程A中调用methodA,在线程B中调用methodB,这样会导致先获取类锁的线程先执行,其他线程阻塞。前提是在先执行的线程中没有改变该静态变量的内存地址。若改变了,那么线程会按CPU调度运行。因为synchronized锁的是变量的那个内存位置,若后面改变了该变量的内存位置,在其他方法中比对当前位置与被锁位置不一致,则会执行。
public static void main(String []ags) throws Exception{ final C c=new C(); final C c1=new C(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.staticString1(); } }).start(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.staticString2(); } }).start(); }
结果:
顺序改变一下:(先执行的线程没有改变地址)
public static void main(String []ags) throws Exception{ final C c=new C(); final C c1=new C(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.staticString2(); } }).start(); new Thread(new Runnable() { @Override public void run() { // TODO 自动生成的方法存根 c.staticString1(); } }).start(); }
结果:
- Java中的synchronized关键字
- java的synchronized关键字
- java中的synchronized关键字
- java中的synchronized关键字
- java中的synchronized关键字
- Java中的synchronized关键字
- Java synchronized关键字
- java中的synchronized关键字
- java synchronized关键字
- java synchronized 关键字
- Java的关键字synchronized
- java关键字synchronized
- java synchronized关键字理解
- Java中的synchronized关键字
- java中的synchronized关键字
- JAVA synchronized 关键字
- java中的synchronized关键字
- Java synchronized关键字详解
- hadoop入门(九)Mapreduce中的简单排序(手机流量排序)
- 【开发工具】 JEECG_3.7新版开发工具
- 基于变分自编码器的生成对抗网络
- 算法分析与设计课程作业第二周#1
- 静态方法、实例方法、构造器
- java synchronized关键字
- 《部落冲突:皇室战争》——一款不能错过的游戏!
- Vue 父组件与子组件之间的通信
- 部分A+B (15)
- Ubuntu更改默认python版本的两种方法
- 第五节 hive的安装
- 特质的继承层级
- 判断GPS省市/区县非API调用方法
- 2017 ACM-ICPC 亚洲区(西安赛区)网络赛