java concurrent之前戏synchronized

对于多线程共享资源的情况须要进行同步,以避免一个线程的修改被还有一个线程的修改所覆盖。

最普遍的同步方式就是synchronized。

把代码声明为synchronized。有两个重要后果,一般是指该代码具有 原子性(atomicity)和 可见性(visibility)。

1、原子性强调的是运行。意味着个时刻,仅仅有一个线程可以运行一段代码,这段代码通过一个monitor object保护。从而防止多个线程在更新共享状态时相互冲突。

2、可见性强调的是结果。它要对付内存缓存和编译器优化的各种反常行为。它必须确保释放锁之前对共享数据做出的更改对于随后获得该锁的还有一个线程是可见的。

同步方法

看一个样例就明确了:
import java.util.Random;

public class TestSyncClass {
 private int num=0;
 
 private Random random=new Random();
 
 public synchronized void testAdd1(){
  System.out.println("testAdd1--->>");
  num++;
  try {
   Thread.sleep(1000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  System.out.println("1-result-->>"+num);
 }
 
 public synchronized void testAdd2(){
  System.out.println("testAdd2--->>");
  num++;
  try {
   Thread.sleep(1000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  System.out.println("2-result-->>"+num);
 }
 
 public  void testAdd3(){
  System.out.println("testAdd3--->>");
  num++;
  try {
   Thread.sleep(1000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  System.out.println("3-result-->>"+num);
 }
 
 public static void main(String[] args) {
  final TestSyncClass syncClass=new TestSyncClass();
  Thread thread1=new Thread(){
   @Override
   public void run() {
    syncClass.testAdd1();
    super.run();
   }
  };
  
  Thread thread2=new Thread(){
   @Override
   public void run() {
    syncClass.testAdd2();
    super.run();
   }
  };
  
  Thread thread3=new Thread(){
   @Override
   public void run() {
    syncClass.testAdd3();
    super.run();
   }
  };
  
  thread1.start();
  thread2.start();
  thread3.start();
 }

}

代码执行结果:
testAdd1--->>
testAdd3--->>
1-result-->>2
3-result-->>2
testAdd2--->>
2-result-->>3

代码中testAdd1、testAdd2是被synchronized声明的方法。testAdd3没有声明。在执行的时候因为testAdd3没有被声明,所以在紧跟着開始执行testAdd1的时候也执行了testAdd3。结果testAdd1执行的结果被testAdd3的结果覆盖了,打印了同样的值3。这个主要是可见性的问题。因为testAdd2也是被声明过的,所以testAdd2并没有马上执行。而是等testAdd1执行完之后才開始执行。

全部对象都自己主动含有单一的锁(也称为监视器monitor object)。

当在对象上调用其随意synchronized方法的时候,此对象都被加锁。这时该对象上的其它synchronized方法仅仅有等到前一个方法调用完成并释放了锁之后才干被调用。

针对每一个类,也有一个锁(作为类的Class对象的一部分)。所以synchronized static 方法能够在类的范围内防止对static数据的并发訪问。

同步块

不管何种情况,要想锁住代码,必须使用同样的锁。比如把testAdd2改成
        private Object object=new Object();
 public void testAdd2(){
  synchronized(object){
   System.out.println("testAdd2--->>");
   num++;
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println("2-result-->>"+num);
  }
 }
则testAdd2和testAdd1就不会相互等待了。结果例如以下:
testAdd2--->>
testAdd3--->>
testAdd1--->>
3-result-->>3
2-result-->>3
1-result-->>3

事实上synchronized(object)是更安全的上锁方式。由于直接声明方法的形式用的是类的锁,而声明代码块的形式用的是私有属性的锁,尤其是在server开发的时候,外面类的锁非常easy被黑客获取。从而获取了攻击server的入口,而私有属性的私有性让黑客难以获取,所以它的锁就相对安全的多。

类同步

上面的main方法的三个线程用的是同一个TestSyncClass syncClass对象。假设每一个线程都各自创建一个对象就不能达到锁定代码的目标了。要想达到同步的目的,代码须要改动成例如以下:

import java.util.Random;

public class TestSyncClass {
 private int num = 0;

 private static Object object = new Object();

 private Random random = new Random();

 public void testAdd1() {
  synchronized (object) {
   System.out.println("testAdd1--->>");
   num++;
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println("1-result-->>" + num);
  }
 }

 public void testAdd2() {
  synchronized (object) {
   System.out.println("testAdd2--->>");
   num++;
   try {
    Thread.sleep(1000);
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println("2-result-->>" + num);
  }
 }

 public void testAdd3() {
  System.out.println("testAdd3--->>");
  num++;
  try {
   Thread.sleep(1000);
  } catch (InterruptedException e) {
   e.printStackTrace();
  }
  System.out.println("3-result-->>" + num);
 }

 public static void main(String[] args) {
  Thread thread1 = new Thread() {
   @Override
   public void run() {
    TestSyncClass syncClass = new TestSyncClass();
    syncClass.testAdd1();
    super.run();
   }
  };

  Thread thread2 = new Thread() {
   @Override
   public void run() {
    TestSyncClass syncClass = new TestSyncClass();
    syncClass.testAdd2();
    super.run();
   }
  };

  Thread thread3 = new Thread() {
   @Override
   public void run() {
    TestSyncClass syncClass = new TestSyncClass();
    syncClass.testAdd3();
    super.run();
   }
  };

  thread1.start();
  thread2.start();
  thread3.start();
 }

}

执行结果:

testAdd1--->>
testAdd3--->>
3-result-->>1
1-result-->>1
testAdd2--->>
2-result-->>1

事实上使用synchronized (TestSyncClass.class)类的锁也能达到类似的效果,可是考虑到私有属性的安全性就直接使用上面代码做实例了。

注意:synchronized是不能继承的,父类中synchronized的声明在子类的继承过程中须要再次声明,否则synchronized将会丢失。

wait(), notify()。notifyAll()

基类不光有锁。还有这三个方法。wait()会让获取锁的线程等待并释放锁,直到notify()或notifyAll()唤醒并又一次获取锁。

先看一个样例:
public class TestSyncClass {
 private int num = 0;

 private Object object = new Object();

 private Object object1 = new Object();

 public  void testAdd(int index) {
  System.out.println("testAdd" + index + "--->>");
  synchronized (object) {
   num++;
   try {
    object.wait();
   } catch (InterruptedException e) {
    e.printStackTrace();
   }
   System.out.println(index + "-result-->>" + num);
  }
 }

 public void release() {
  synchronized (object) {
   object.notifyAll();
   System.out.println("-release-->>");
  }
 }

 public static void main(String[] args) {
  final TestSyncClass syncClass = new TestSyncClass();
  Thread thread1 = new Thread() {
   @Override
   public void run() {
    syncClass.testAdd(1);
    super.run();
   }
  };

  Thread thread2 = new Thread() {
   @Override
   public void run() {
    syncClass.testAdd(2);
    super.run();
   }
  };

  Thread thread3 = new Thread() {
   @Override
   public void run() {
    syncClass.testAdd(3);
    super.run();
   }
  };

  thread1.start();
  thread2.start();
  thread3.start();

  Thread thread4 = new Thread() {
   @Override
   public void run() {
    try {
     Thread.sleep(2000);
    } catch (InterruptedException e) {
     e.printStackTrace();
    }
    syncClass.release();
    super.run();
   }
  };
  thread4.start();
 }

}

执行结果:
testAdd1--->>
testAdd2--->>
testAdd3--->>
-release-->>
3-result-->>3
2-result-->>3
1-result-->>3

调用object的wait(), notify()。notifyAll()法前,必须获得object锁,也就是这三个方法必须写在synchronized(obj) {…} 代码段内。否则跑出异常java.lang.IllegalMonitorStateException。


调用object.wait()后。线程A就释放了object的锁,否则syncClass.release()无法获得object锁,等待的线程。


当object.wait()方法返回后。各个线程须要再次获得object锁,才干继续运行。
notify()仅仅能唤醒线程,notifyAll()则能所有唤醒,可是个线程须要又一次竞争object的锁。

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/285717.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

开源项目【zheng】搭建流程

2019独角兽企业重金招聘Python工程师标准>>> 搭建过程 项目地址 https://gitee.com/shuzheng/zheng这两篇写的比较详细的搭建过程,结合一下就没什么问题了。 https://my.oschina.net/yzuzhang/blog/1538555http://www.jianshu.com/p/b2fb42e17b581.JDK 1…

简述HTML DOM及其节点分类

在JavaScript中,document这个对象大家一定很熟悉,哪怕是刚刚开始学习的新人,也会很快接触到这个对象。而document对象不仅仅是一个普通的JavaScript内置对象,它还是一个巨大API的核心对象,这个巨大的API就是DOM&#x…

【CC精品教程】任务二:导入像控点、差分POS,空三平差权重设置,提交自由空三

《无人机航空摄影测量精品教程》合集目录(Pix4d、CC、EPS、PhotoScan、Inpho) 【CC精品教程】任务一:CC新建工程、添加照片、相机参数设置、选择坐标系统 本任务接着上一个任务,继续完成CC项目作业,主要内容有:导入像控点、选择空间参考系统,导入差分POS,空三平差权重设…

[转]如何进行单元测试

一、单元测试步骤 代码编写完成后的单元测试工作主要分为两个步骤: 人工静态检查 人工静态检查是测试的第一步,这个阶段工作主要是保证代码算法的逻辑正确性(尽量通过人工检查发现代码的逻辑错误)、清晰性、规范性、一致性、算法…

WPF 基础控件之 TabControl样式

其他基础控件1.Window2.Button3.CheckBox4.ComboBox5.DataGrid 6.DatePicker7.Expander8.GroupBox9.ListBox10.ListView11.Menu12.PasswordBox13.TextBox14.RadioButton15.ToggleButton16.Slider 17.TreeView TabControl 实现下面的效果1)TabControl来实现动画&…

开发团队测试的难与易

做了多年的研发工程师,在所处的环境中,所接触的开发人员中很少有看重对自己代码进行测试这项工作的。大多研发人员往往是写好了代码运行起来,简单做下测试,甚至不去测试就抛给接口使用者或者质量管理人员。而且理由很充分“没时间…

C语言试题八十八之实现选冒泡排序算法

📃个人主页:个人主页 🔥系列专栏:C语言试题200例目录 💬推荐一款刷算法、笔试、面经、拿大公司offer神器 👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 C语言实现冒…

两个数值交换位置

2019独角兽企业重金招聘Python工程师标准>>> 先说非计算机专业都能理解的。 int a 10; int b 20; 方法一: int c a; a b; b c; System.out.println("a"a",b"b); 方法二: a a b; b a - b; a a - b; System.out…

教你如何在Android 6.0上创建系统悬浮窗

郭霖大神的文章:http://mp.weixin.qq.com/s?__bizMzA5MzI3NjE2MA&mid2650235949&idx1&sn0f7eded67f834d38b02f8872768cb68a&scene0#wechat_redirect今天周二,又该跟大家分享由我执笔的文章了。从之前我写的deep links、通知栏微技巧这两篇文章中&a…

【CC精品教程】任务三:CC刺像控点,提交空三,新建重建项目(三维格网、三维点云、DOM和DSM)

《无人机航空摄影测量精品教程》合集目录(Pix4d、CC、EPS、PhotoScan、Inpho) 【CC精品教程】任务一:CC新建工程、添加照片、相机参数设置、选择坐标系统 【CC精品教程】任务二:导入像控点、差分POS,空三平差权重设置,提交自由空三 主要任务是准确的刺像控点,提交空三,…

官宣.NET 7 预览版5

点击上方蓝字关注我们(本文阅读时间:12分钟)今天我们发布了 .NET 7 预览版 5。.NET 7 的这个预览版包括对通用数学的改进,方便了 API 作者,使其更轻松,一个新的 ML.NET 文本分类 API,增加了最先进的深度学习…

[转]Android产品研发(十九)

转载请标明出处:一片枫叶的专栏 上一篇文章中我们讲解了webview中问题集锦,讲解了webview的性能优化、webview种入Cookie信息、activity退出的时候清除webview信息报错、如何通过java代码和js代码相互交互、webview如何下载文件以及腾讯的X5浏览服务等知…

C语言试题八十九之实现插入排序算法

📃个人主页:个人主页 🔥系列专栏:C语言试题200例目录 💬推荐一款刷算法、笔试、面经、拿大公司offer神器 👉 点击跳转进入网站 ✅作者简介:大家好,我是码莎拉蒂,CSDN博客专家(全站排名Top 50),阿里云博客专家、51CTO博客专家、华为云享专家 1、题目 C语言实现现…

【CC精品教程】ContextCapture 10.17安装教程(附CC10.17安装包下载)

《无人机航空摄影测量精品教程》合集目录(Pix4d、CC、EPS、PhotoScan、Inpho) CC10.17相比之前的版本有了好的新的功能和优点,在倾斜摄影测量中有了更多的优势,精度和运行速度有了很大的提升。本文讲解CC的安装,附CC10.17安装包下载,是您航测倾斜摄影测量的入门必备。 文…

centos7 kickstart 使用小结

1、添加参数使网卡名称变为eth 1bootloader --locationmbr --append"net.ifnames0 biosdevname0 rhgb quiet" 2、psize使用说明:修改vg PE16m 默认4m 支持256G磁盘,适当的调整pesize,可以更多的使用磁盘空间 1volgroup Vol1--pesize16384 pv.…

IOS-网络(文件上传)

1 //2 // ViewController.m3 // IOS_0206_文件上传4 //5 // Created by ma c on 16/2/6.6 // Copyright © 2016年 博文科技. All rights reserved.7 //8 9 #import "ViewController.h"10 #define BWFileBoundary "----------BowenKeJi"11 #define…

mac SecureCRT设置

参考: http://www.2cto.com/os/201407/320292.html SecureCRT 设置 1)每次登陆都要输入密码: Global Option -> General 取消:Use Keychain前面的勾 2)Logon Actions Logon Actions很强大,和python里…

【微服务专题之】.Net6下集成消息队列上-RabbitMQ

微信公众号:趣编程ACE关注可了解更多的.NET日常实战开发技巧,如需源码 请公众号后台留言 源码;[如果觉得本公众号对您有帮助,欢迎关注].Net中RabbitMQ的使用超清观看视频哦~官网链接RabbitMQ代码演示-详细见代码注释,操作看上文视…

[转]总结:Apache/Tomcat/JBOSS/Jetty/Nginx区别 .

总结:Apache/Tomcat/JBOSS/Nginx区别 . 1、Apache是Web服务器,Tomcat是应用(Java)服务器。Tomcat在中小型系统和并发访问用户不是很多的场合下被普遍使用。Apache支持静态页,Tomcat支持动态的。 2、Jetty:Tomcat内核作…

华为云GaussDB,11.11让企业无后顾之忧

每年11.11大促对于数据库而言都是一场生死考验,如何保障系统的稳定可靠,如何平稳度过业务流量洪峰期,如何高效扩容,成为每个参与活动客户的一大痛点。本文将通过5个常见的大促问题及分析,看看华为云GaussDB是如何解决这…