范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Java并发编程synchronized

  虽然多线程编程极大地提高了效率,但是也会带来一定的隐患。比如说两个线程同时往一个数据库表中插入不重复的数据,就可能会导致数据库中插入了相同的数据。今天我们就来一起讨论下线程安全问题,以及Java中提供了什么机制来解决线程安全问题。
  以下是本文的目录大纲:
  一.什么时候会出现线程安全问题?
  二.如何解决线程安全问题?
  三.synchronized同步方法或者同步块
  若有不正之处,请多多谅解并欢迎批评指正。
  请尊重作者劳动成果,转载请标明原文链接:
  http://www.cnblogs.com/dolphin0520/p/3923737.html
  一.什么时候会出现线程安全问题?
  在单线程中不会出现线程安全问题,而在多线程编程中,有可能会出现同时访问同一个资源的情况,这种资源可以是各种类型的的资源:一个变量、一个对象、一个文件、一个数据库表等,而当多个线程同时访问同一个资源的时候,就会存在一个问题:
  由于每个线程执行的过程是不可控的,所以很可能导致最终的结果与实际上的愿望相违背或者直接导致程序出错。
  举个简单的例子:
  现在有两个线程分别从网络上读取数据,然后插入一张数据库表中,要求不能插入重复的数据。
  那么必然在插入数据的过程中存在两个操作:
  1)检查数据库中是否存在该条数据;
  2)如果存在,则不插入;如果不存在,则插入到数据库中。
  假如两个线程分别用thread-1和thread-2表示,某一时刻,thread-1和thread-2都读取到了数据X,那么可能会发生这种情况:
  thread-1去检查数据库中是否存在数据X,然后thread-2也接着去检查数据库中是否存在数据X。
  结果两个线程检查的结果都是数据库中不存在数据X,那么两个线程都分别将数据X插入数据库表当中。
  这个就是线程安全问题,即多个线程同时访问一个资源时,会导致程序运行结果并不是想看到的结果。
  这里面,这个资源被称为:临界资源(也有称为共享资源)。
  也就是说,当多个线程同时访问临界资源(一个对象,对象中的属性,一个文件,一个数据库等)时,就可能会产生线程安全问题。
  不过,当多个线程执行一个方法,方法内部的局部变量并不是临界资源,因为方法是在栈上执行的,而Java栈是线程私有的,因此不会产生线程安全问题。
  二.如何解决线程安全问题?
  那么一般来说,是如何解决线程安全问题的呢?
  基本上所有的并发模式在解决线程安全问题时,都采用"序列化访问临界资源"的方案,即在同一时刻,只能有一个线程访问临界资源,也称作同步互斥访问。
  通常来说,是在访问临界资源的代码前面加上一个锁,当访问完临界资源后释放锁,让其他线程继续访问。
  在Java中,提供了两种方式来实现同步互斥访问:synchronized和Lock。
  本文主要讲述synchronized的使用方法,Lock的使用方法在下一篇博文中讲述。
  三.synchronized同步方法或者同步块
  在了解synchronized关键字的使用方法之前,我们先来看一个概念:互斥锁,顾名思义:能到达到互斥访问目的的锁。
  举个简单的例子:如果对临界资源加上互斥锁,当一个线程在访问该临界资源时,其他线程便只能等待。
  在Java中,每一个对象都拥有一个锁标记(monitor),也称为监视器,多线程同时访问某个对象时,线程只有获取了该对象的锁才能访问。
  在Java中,可以使用synchronized关键字来标记一个方法或者代码块,当某个线程调用该对象的synchronized方法或者访问synchronized代码块时,这个线程便获得了该对象的锁,其他线程暂时无法访问这个方法,只有等待这个方法执行完毕或者代码块执行完毕,这个线程才会释放该对象的锁,其他线程才能执行这个方法或者代码块。
  下面通过几个简单的例子来说明synchronized关键字的使用:
  1.synchronized方法
  下面这段代码中两个线程分别调用insertData对象插入数据:
  1
  2
  3
  4
  5
  6
  7
  8
  9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  public class Test {   public static void main(String[] args) {   final InsertData insertData = new InsertData();   new Thread() {   public void run() {   insertData.insert(Thread.currentThread());   };   }.start();   new Thread() {   public void run() {   insertData.insert(Thread.currentThread());   };   }.start();   }   }   class InsertData {   private ArrayList arrayList = new ArrayList();   public void insert(Thread thread){   for(int i=0;i<5;i++){   System.out.println(thread.getName()+"在插入数据"+i);   arrayList.add(i);   }   }   }   此时程序的输出结果为:   说明两个线程在同时执行insert方法。   而如果在insert方法前面加上关键字synchronized的话,运行结果为:   1
  2
  3
  4
  5
  6
  7
  8
  9
  10
  class InsertData {   private ArrayList arrayList = new ArrayList();   public synchronized void insert(Thread thread){   for(int i=0;i<5;i++){   System.out.println(thread.getName()+"在插入数据"+i);   arrayList.add(i);   }   }   }   从上输出结果说明,Thread-1插入数据是等Thread-0插入完数据之后才进行的。说明Thread-0和Thread-1是顺序执行insert方法的。   这就是synchronized方法。   不过有几点需要注意:   1)当一个线程正在访问一个对象的synchronized方法,那么其他线程不能访问该对象的其他synchronized方法。这个原因很简单,因为一个对象只有一把锁,当一个线程获取了该对象的锁之后,其他线程无法获取该对象的锁,所以无法访问该对象的其他synchronized方法。   2)当一个线程正在访问一个对象的synchronized方法,那么其他线程能访问该对象的非synchronized方法。这个原因很简单,访问非synchronized方法不需要获得该对象的锁,假如一个方法没用synchronized关键字修饰,说明它不会使用到临界资源,那么其他线程是可以访问这个方法的,   3)如果一个线程A需要访问对象object1的synchronized方法fun1,另外一个线程B需要访问对象object2的synchronized方法fun1,即使object1和object2是同一类型),也不会产生线程安全问题,因为他们访问的是不同的对象,所以不存在互斥问题。   2.synchronized代码块   synchronized代码块类似于以下这种形式:   1
  2
  3
  synchronized(synObject) {   }   当在某个线程中执行这段代码块,该线程会获取对象synObject的锁,从而使得其他线程无法同时访问该代码块。   synObject可以是this,代表获取当前对象的锁,也可以是类中的一个属性,代表获取该属性的锁。   比如上面的insert方法可以改成以下两种形式:   1
  2
  3
  4
  5
  6
  7
  8
  9
  10
  11
  12
  class InsertData {   private ArrayList arrayList = new ArrayList();   public void insert(Thread thread){   synchronized (this) {   for(int i=0;i<100;i++){   System.out.println(thread.getName()+"在插入数据"+i);   arrayList.add(i);   }   }   }   }   1
  2
  3
  4
  5
  6
  7
  8
  9
  10
  11
  12
  13
  class InsertData {   private ArrayList arrayList = new ArrayList();   private Object object = new Object();   public void insert(Thread thread){   synchronized (object) {   for(int i=0;i<100;i++){   System.out.println(thread.getName()+"在插入数据"+i);   arrayList.add(i);   }   }   }   }   从上面可以看出,synchronized代码块使用起来比synchronized方法要灵活得多。因为也许一个方法中只有一部分代码只需要同步,如果此时对整个方法用synchronized进行同步,会影响程序执行效率。而使用synchronized代码块就可以避免这个问题,synchronized代码块可以实现只对需要同步的地方进行同步。   另外,每个类也会有一个锁,它可以用来控制对static数据成员的并发访问。   并且如果一个线程执行一个对象的非static synchronized方法,另外一个线程需要执行这个对象所属类的static synchronized方法,此时不会发生互斥现象,因为访问static synchronized方法占用的是类锁,而访问非static synchronized方法占用的是对象锁,所以不存在互斥现象。   看下面这段代码就明白了:   1
  2
  3
  4
  5
  6
  7
  8
  9
  10
  11
  12
  13
  14
  15
  16
  17
  18
  19
  20
  21
  22
  23
  24
  25
  26
  27
  28
  29
  30
  31
  32
  33
  34
  35
  public class Test {   public static void main(String[] args) {   final InsertData insertData = new InsertData();   new Thread(){   @Override   public void run() {   insertData.insert();   }   }.start();   new Thread(){   @Override   public void run() {   insertData.insert1();   }   }.start();   }   }   class InsertData {   public synchronized void insert(){   System.out.println("执行insert");   try {   Thread.sleep(5000);   } catch (InterruptedException e) {   e.printStackTrace();   }   System.out.println("执行insert完毕");   }   public synchronized static void insert1() {   System.out.println("执行insert1");   System.out.println("执行insert1完毕");   }   }   执行结果;   第一个线程里面执行的是insert方法,不会导致第二个线程执行insert1方法发生阻塞现象。   下面我们看一下synchronized关键字到底做了什么事情,我们来反编译它的字节码看一下,下面这段代码反编译后的字节码为:   1
  2
  3
  4
  5
  6
  7
  8
  9
  10
  11
  12
  13
  14
  15
  16
  17
  public class InsertData {   private Object object = new Object();   public void insert(Thread thread){   synchronized (object) {   }   }   public synchronized void insert1(Thread thread){   }   public void insert2(Thread thread){   }   }   从反编译获得的字节码可以看出,synchronized代码块实际上多了monitorenter和monitorexit两条指令。monitorenter指令执行时会让对象的锁计数加1,而monitorexit指令执行时会让对象的锁计数减1,其实这个与操作系统里面的PV操作很像,操作系统里面的PV操作就是用来控制多个线程对临界资源的访问。对于synchronized方法,执行中的线程识别该方法的 method_info 结构是否有 ACC_SYNCHRONIZED 标记设置,然后它自动获取对象的锁,调用方法,最后释放锁。如果有异常发生,线程自动释放锁。   有一点要注意:对于synchronized方法或者synchronized代码块,当出现异常时,JVM会自动释放当前线程占用的锁,因此不会由于异常导致出现死锁现象。   参考资料:   《Java编程思想》   Java同步块 | 并发编程网 – ifeve.com   聊聊并发(二)Java SE1.6中的Synchronized | 并发编程网 – ifeve.com

天冷了,一物多用的暖宫带女孩子必备哦最近上手了这款得小烯暖宫带,给大家分享一下外观粉粉嫩嫩,很适合女孩子用机身小巧,圆润,作为暖手宝手感也特别好(同事一男孩子老给我拿走)。硅胶套也特别软,上手也很光滑。那弹力带可调节中国电信移动联通,以目前发展规划而言哪个更适应时代发展?4G已经来到身边,作为一个同时使用过中国移动中国电信和中国联通的人,和大家分享一下经验。工具原料手机4G网络速度1在信号强度都很好的情况下测试!中国移动采用的是TDLET网络,实际爱立信扛不住了?中国变相裁员员工变外包,不接受拿N1赔偿撰文AI财经社康嘉林编辑赵艳秋爱立信南京研发中心裁员又有新动向。根据爱立信的安排,从2021年11月1日起,爱立信南京研发中心将把630名员工的劳动关系转移至其全球长期伙伴Tiet工信部发布第二批5G工业互联网典型应用场景新华社北京11月22日电(记者张辛欣)记者22日从工信部获悉,工信部发布第二批5G工业互联网典型应用场景和重点行业实践。厂区智能理货全域物流监测这些正作为典型应用场景,在越来越多的11月24日早读丨你不能错过的新闻都在这里第九批网络主播警示名单公布包括吴亦凡郑爽等中国演出行业协会网络表演(直播)分会确定出第九批网络表演(直播)行业主播警示名单(共计88名)。值得注意的是,本批次会员企业报送的警示名单帕丽斯希尔顿(ParisHilton)感染NFT,押注ORIGYN融资2000万美元我们专注一级市场,每天发布币圈潜力优势币种,欢迎同好关注。社交名媛帕丽斯希尔顿(ParisHilton)对加密领域产生了浓厚的兴趣,尤其是对不可替代的代币(NFT)。根据新闻稿,希买买买变退退退双11高退货率背后乱象频生本报记者贾丽双11盛宴落下帷幕,全网交易额再创历史新高。不过,有一个数据,各平台对外却不愿过多提及,那就是退货率。据证券日报记者了解,双11期间,淘宝退货率在20以上京东约为10,硬汉再升级!OLIGHT武士WarriorX3战术手电体验武士(Warrior)家族作为傲雷(Olight)旗下经典系列,可谓人才济济。涌现出专注于通勤便携的EDC筒武士mini,经典小直M2RPRO,以及主打战术远射的武士XXP等一大批了解手机电池的特性,延缓电池老化速度首先提出疑问快充废电池吗?bingo!那首先要知道一点,电池是消耗品,对电池造成不可逆的损耗那就是充电次数翻,跟用不用快充没有任何关系,就像验机也只看充电次数没有谁会去了解一下这个据说小米vela已经全球第一,都有哪些产品搭载了呢?没听说过这个东西这是物联网系统,基于NuttX系统研发,搭载在智能家居产品上,生活中感受不太明显,但的确是世界第一。谢邀,目前不关注这个。谢谢。物联网行业,智能家居,按照现在的市场工信部启动新能源汽车换电模式应用试点工作,11个城市纳入试点范围工信微报微信公众号10月28日消息,日前,工业和信息化部办公厅印发关于启动新能源汽车换电模式应用试点工作的通知(以下简称通知),决定启动新能源汽车换电模式应用试点工作。纳入此次试点
十四年前卖3000的笔记本电脑,如今100块买来玩玩,外壳都包浆了遥想2007年,华硕推出了全球首款超便携电脑EPC700,不但体积小巧方便携带,关键是价格还便宜,只要三千块钱就能买到。这可比同期的索尼UMPC要便宜太多了,可惜当时嫌处理器配置太辛巴要起诉快手?独家回应来了网络主播辛巴传出对直播平台快手提出起诉的消息。据南方记者从天眼查APP了解到,近日,北京快手科技有限公司新增两则开庭公告,分别为辛有志与北京快手科技有限公司相关网络侵权责任纠纷时诗折叠屏是又一个8848?图片来源视觉中国文市值榜,作者张择瑞,编辑嘉辛一个人一天要在手机上花费多少时间?截至今年9月,这个数字是6。6个小时。作为对比,4G铺开前夜的2013年,近80的网民使用手机的时长今天的百度阿里腾讯京东拼多多就是古代的地主古代的地主是由分封继承来的。地主指家庭拥有土地,其成员不参加劳动的人。封建社会里最大的地主为皇帝,拥有全国土地,其它的根据级别之类的划分。从大地主下划到小地主,最后划到级别最低的农Javaweb学习(六)JavaBean技术JavaBean技术题量16满分100作答时间11091922至12301922重做100分一。单选题(共8题,49。6分)1。不是JavaBean属性的项为()。A。constr8家网盘迎月考5家完成改造11月17日,工信部组织百度网盘腾讯微云天翼云盘和彩云阿里云盘迅雷云盘360安全云盘和网易网盘等首批8家网盘企业在北京共同签署个人网盘服务业务用户体验保障自律公约(简称公约),旨在阿里云被锤喜闻乐见?阿里到底出了什么问题?没有网络安全就没有国家安全,就没有经济社会稳定运行,广大人民群众利益也难以得到保障。国家安全问题不容有失!!!前有滴滴事件,遭到了国家信息部门的核查,并且被核马斯克星链最新网速延迟实测宽带看完笑了头部消息1滴滴或以介绍形式赴香港上市据报道,滴滴(DIDI)或通过介绍形式来港上市,以满足港交所上市要求,一般以介绍形式上市的股份为公司的已发行股份,因此公司不会发行新股,亦不会筹天才女博士毛蔚放弃硅谷百万高薪,回国帮助华为解决芯片荒文明煜编辑明煜论点她的名字叫毛蔚,是公认的世界第一才女,17岁为国争光一人独揽奥林匹克物理竞赛的三项大奖,随后被清华大学破格录取,毕业后出国留学,仅用两年时间就顺利获得了加州大学的5000mAh鸿蒙OS,华为手机仅929元在过去很长一段时间,国内市场份额排名第一的是华为,作为国内老字号的手机巨头,华为手机不仅搭载自主麒麟芯片,还开发出了配套的鸿蒙OS系统,得到网友一致认可。早些时候,荣耀也是属于华为浅析我国数字乡村建设近年来,信息技术创新空前活跃,不断催生出新技术新产品新模式,推动全球经济格局和产业形态的深度变革,为数字乡村发展创造了前所未有的重大机遇。全球新一轮技术变革背景下,以物联网大数据区