文档章节

java资源锁synchronized说“给我一把 锁,我能创造一个规矩”

丈量大地
 丈量大地
发布于 2014/06/11 14:11
字数 1217
阅读 122
收藏 9
点赞 5
评论 0

在java多线程编程中,我们需要对java对象中的资源进行同步管理,确保在同一时刻,只能由同一线程访问类或者对象中的资源,这样可以防止由于几个线程共享同一资源导致不可知的后果。

方法之一就是利用资源锁(synchronized),废话少说,先上例子

例子一

public class S_1 {
 public static void main(String[] args) {
  for(int i=0;i<5;i++){
   new Thread_1().start();
  }
 }
}

class Thread_1 extends Thread{
 @Override
 public synchronized void run() {
  for(int i=0;i<100;i++){
   System.out.println(i);
  }
 }
 
}

例子二:

public class S_2 {
 public static void main(String[] args) {
  for(int i=0;i<5;i++){
   new Thread_2().start();
  }
 }
}
class Thread_2 extends Thread{
 @Override
 public void run(){
  synchronized(this){
   for(int i=0;i<100;i++){
    System.out.println(i);
   }
  }
 }
}

例子三:


public class S3 {
 public static void main(String[] args) {
  for(int i=0;i<5;i++){
   new Thread_3().start();
  }
 }
}
class Thread_3 extends Thread{
 public synchronized static void show(){
  for(int i=0;i<100;i++){
   System.out.println(i);
  }
 }
 @Override
 public void run(){
  show();
 }

}

例子四:

public class S_4 {
 public static void main(String[] args) {
  for(int i=0;i<5;i++){
   String lock = "lock";
   new Thread_4(lock).start();
  }
 }
}
class Thread_4 extends Thread{
 private String lock ;
 public Thread_4(String lock){
  this.lock = lock ;
 }
 @Override
 public void run(){
  synchronized(lock){
   for(int i=0;i<100;i++){
    System.out.println(i);
   }
  }
 }
 
}
以上四个例子是用五个线程从0-99进行打印,他们都是按照先后顺序从0-99进行打印的吗?如果你的答案是按顺序依次打印的话,那你就错了,下边我一一来讲解下

例子一,没有按照先后顺序进行打印。我们对run方法进行了加锁,按理说是该按照先后顺序进行打印的,但是为什么结果与我们想象的不一样呢?由于我们起五个线程的时候,我们创建了五个Thread_1对象,这样每个线程都获取了一个对象,每个线程都获取了自己对象中run方法的锁,所以,这里的资源锁是没有意义的,如果要让这里的锁起作用,除非该Thread_1是单例模式的,这样这些线程都共享一个对象,才会按照先后顺序获取锁

例子二,没有按照先后顺序进行打印。我们对run方法中的一部分代码进行了synchronized块保护,也应该按照每个线程依次打印,但为什么还是没有依次打印呢?由于我们synchronized(this)中的this在五个线程中是没有共享的,五个线程中的this都不一样,这样相当于对五个对象进行资源块进行保护,五个线程依然能够同时获取synchronized(this)方法中的代码执行的锁

例子三,按照先后顺序打印。这个例子可以和例子一对应起来看,我们是在show方法上加的锁,并且show方法是static的,这样这里方法就是类方法,被所以对象共享的,当我们起五个线程,这五个线程对show方法是共享的,而且该方法被加锁了,当线程来访问的时候,首先看这个方法是否被其他线程使用,如果正在被其他对象使用,对不起,你先等着,等下一个线程用完了,退出了的时候,线程池中轮到你的时候,你才能执行该方法

例子四,按照先后顺序打印。这个例子可以和例子四对应起来看,首先我们来看下例子4,类Thread_4是一个继承Thread的线程类,他有一个私有变量lock,在其run方法中,我们用锁块对要打印的语句进行保护,我们在启动线程的时候,通过构造方法,给Thread_4的lock变量进行赋值,由于我们启动的五个线程中,每个Thread对象的lock变量的值都是同一个,即五个线程共享变量lock,所以要执行被synchronized方法锁起来的语句,也必须获得相应的锁才能够执行,对比例子一种,this的值在每个线程中不一样的

 

最后总结

如果我们想通过synchronized来修辞方法,来达到在同一时刻,该方法只能被同一线程访问的话,有两个条件

条件一:线程对象是一个单例类

条件二:synchronized修饰的方法是static的

如果我们想通过synchronized方法来达到在同一时刻,被保护的语句块只能被同一线程访问,其条件是

synchronized方法中传入的对象必须是共享的,即传入的对象必须是一样的

 

希望这篇博文对你有用,如果我对synchronized认识不到位的地方,请多多指教

 

 

 

    

 

 

© 著作权归作者所有

共有 人打赏支持
丈量大地

丈量大地

粉丝 15
博文 32
码字总数 27634
作品 0
都江堰
程序员
Java多线程学习(二)synchronized关键字(2)

系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Ja...

一只蜗牛呀 ⋅ 04/16 ⋅ 0

Java多线程学习(四)等待/通知(wait/notify)机制

系列文章传送门: Java多线程学习(一)Java多线程入门 Java多线程学习(二)synchronized关键字(1) java多线程学习(二)synchronized关键字(2) Java多线程学习(三)volatile关键字 Ja...

一只蜗牛呀 ⋅ 04/16 ⋅ 0

悲观的并发策略——synchronized互斥锁

互斥锁是最常见的同步手段,在并发过程中,当多条线程对同一个共享数据竞争时,它保证共享数据同一时刻只能被一条线程使用,其他线程只有等到锁释放后才能重新进行竞争。 对于Java开发人员,...

wangyangzhizhou ⋅ 04/16 ⋅ 0

Java 多线程编程 — 锁优化2

Java多线程编程-(13)- 关于锁优化的几点建议 一、背景 在《 Java多线程编程-(11)-从volatile和synchronized的底层实现原理看Java虚拟机对锁优化所做的努力》 这一篇文章中,我们大致介绍...

晨猫 ⋅ 04/26 ⋅ 0

Java并发--synchronized实现原理及锁优化

注:本文中的部分内容摘抄自他人博客,如有侵权,请联系我,侵删~ 本篇博客主要讲述 synchronized 关键字的实现原理以及 JDK 1.6 后对 synchronized 的种种优化。synchronized 的使用不再赘述...

championhengyi ⋅ 04/27 ⋅ 0

Java 编程之美:并发编程基础晋级篇

本文来自作者 加多 在 GitChat 上分享 「Java 并发编程之美:并发编程基础晋级篇」 编辑 | Mc Jin 借用 Java 并发编程实践中的话,编写正确的程序并不容易,而编写正常的并发程序就更难了! ...

gitchat ⋅ 04/18 ⋅ 0

深入理解多线程(五)—— Java虚拟机的锁优化技术

本文是《深入理解多线程》的第五篇文章,前面几篇文章中我们从synchronized的实现原理开始,一直介绍到了Monitor的实现原理。 前情提要 通过前面几篇文章,我们已经知道: 1、同步方法通过关...

⋅ 04/21 ⋅ 0

21、Java并发性和多线程-Java中的锁

以下内容转自http://ifeve.com/locks/: 锁像synchronized同步块一样,是一种线程同步机制,但比Java中的synchronized同步块更复杂。因为锁(以及其它更高级的线程同步机制)是由synchronize...

easonjim ⋅ 2017/06/16 ⋅ 0

深入浅出Java多线程,看着篇就够了

Java给多线程编程提供了内置的支持。一个多线程程序包含两个或多个能并发运行的部分。程序的每一部分都称作一个线程,并且每个线程定义了一个独立的执行路径。 多线程是多任务的一种特别的形...

java高级架构牛人 ⋅ 05/22 ⋅ 0

【Java并发专题】27篇文章详细总结Java并发基础知识

努力的意义,就是,在以后的日子里,放眼望去全是自己喜欢的人和事! github:https://github.com/CL0610/Java-concurrency,欢迎题issue和Pull request。所有的文档都是自己亲自码的,如果觉...

你听___ ⋅ 05/06 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

java软件工程师简历中项目经验怎么写?

作者:暗灭 链接:https://www.zhihu.com/question/20695310/answer/180691302 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 直接给你贴个我自己的简历...

颖伙虫 ⋅ 27分钟前 ⋅ 0

Confluence 6 恢复一个站点有关使用站点导出为备份的说明

推荐使用生产备份策略。我们推荐你针对你的生产环境中使用的 Confluence 参考 Production Backup Strategy 页面中的内容进行备份和恢复(这个需要你备份你的数据库和 home 目录)。XML 导出备...

honeymose ⋅ 今天 ⋅ 0

JavaScript零基础入门——(九)JavaScript的函数

JavaScript零基础入门——(九)JavaScript的函数 欢迎回到我们的JavaScript零基础入门,上一节课我们了解了有关JS中数组的相关知识点,不知道大家有没有自己去敲一敲,消化一下?这一节课,...

JandenMa ⋅ 今天 ⋅ 0

火狐浏览器各版本下载及插件httprequest

各版本下载地址:http://ftp.mozilla.org/pub/mozilla.org//firefox/releases/ httprequest插件截至57版本可用

xiaoge2016 ⋅ 今天 ⋅ 0

Docker系列教程28-实战:使用Docker Compose运行ELK

原文:http://www.itmuch.com/docker/28-docker-compose-in-action-elk/,转载请说明出处。 ElasticSearch【存储】 Logtash【日志聚合器】 Kibana【界面】 答案: version: '2'services: ...

周立_ITMuch ⋅ 今天 ⋅ 0

使用快嘉sdkg极速搭建接口模拟系统

在具体项目研发过程中,一旦前后端双方约定好接口,前端和app同事就会希望后台同事可以尽快提供可供对接的接口方便调试,而对后台同事来说定好接口还仅是个开始、设计流程,实现业务逻辑,编...

fastjrun ⋅ 今天 ⋅ 0

PXE/KickStart 无人值守安装

导言 作为中小公司的运维,经常会遇到一些机械式的重复工作,例如:有时公司同时上线几十甚至上百台服务器,而且需要我们在短时间内完成系统安装。 常规的办法有什么? 光盘安装系统 ===> 一...

kangvcar ⋅ 昨天 ⋅ 0

使用Puppeteer撸一个爬虫

Puppeteer是什么 puppeteer是谷歌chrome团队官方开发的一个无界面(Headless)chrome工具。Chrome Headless将成为web应用自动化测试的行业标杆。所以我们很有必要来了解一下它。所谓的无头浏...

小草先森 ⋅ 昨天 ⋅ 0

Java Done Right

* 表示难度较大或理论性较强。 ** 表示难度更大或理论性更强。 【Java语言本身】 基础语法,面向对象,顺序编程,并发编程,网络编程,泛型,注解,lambda(Java8),module(Java9),var(...

风华神使 ⋅ 昨天 ⋅ 0

Linux系统日志

linux 系统日志 /var/log/messages /etc/logrotate.conf 日志切割配置文件 https://my.oschina.net/u/2000675/blog/908189 logrotate 使用详解 dmesg 命令 /var/log/dmesg 日志 last命令,调......

Linux学习笔记 ⋅ 昨天 ⋅ 0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部