文档章节

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

丈量大地
 丈量大地
发布于 2014/06/11 14:11
字数 1217
阅读 131
收藏 9

在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认识不到位的地方,请多多指教

 

 

 

    

 

 

© 著作权归作者所有

共有 人打赏支持
丈量大地

丈量大地

粉丝 16
博文 52
码字总数 27634
作品 0
都江堰
程序员
私信 提问
Java多线程学习(二)synchronized关键字(2)

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

一只蜗牛呀
04/16
0
0
15-《深度拆解JVM》之Java虚拟机是怎么实现synchronized的?

一、问题引入 在 Java 程序中,我们可以利用 synchronized 关键字来对程序进行加锁。它既可以用来声明一个 synchronized 代码块,也可以直接标记静态方法或者实例方法。 当声明 synchronized...

飞鱼说编程
11/06
0
0
JVM到底是怎么处理锁的?怎么不让我阻塞呢?

我是一个线程,生活在JVM(Java虚拟机)中, 这一段日子过得有些无聊,整个世界似乎只有这一个人,天天忙着执行代码,想休息一下都很难。 我听说人类写的代码中有些特殊的地方,叫做临界区,...

Java大蜗牛
07/15
0
0
在JAVA中线程到底起到什么作用!

这是javaeye上非常经典的关于线程的帖子,写的非常通俗易懂的,适合任何读计算机的同学. 线程同步 我们可以在计算机上运行各种计算机软件程序。每一个运行的程序可能包括多个独立运行的线程(...

xtof
11/15
0
0
理解 java 中的 synchronized 关键字

实际上,我关于java的基础知识的90%以上都来自Thinking in Java。对于其中的synchronized关键字, 当时就是浏览一下,大概知道意思,也没有细看。后来一直没有用过这个关键字。 昨天看Think...

大数据之路
2012/10/27
0
0

没有更多内容

加载失败,请刷新页面

加载更多

并发+超时示例

func installMantisAgent() {log.Println("begin auto repair mantis agent")num := 0succNum := 0failNum := 0var Q *queue.Queueswitch g.Config().RepairType {ca......

我爱吃葱花
12分钟前
0
0
增加一列自增id

ALTER TABLE xxxx ADD iSiteId INT(11) NOT NULL PRIMARY KEY AUTO_INCREMENT FIRST;

colin_86
21分钟前
2
0
开发函数计算的正确姿势 —— 爬虫

在 《函数计算本地运行与调试 - Fun Local 基本用法》 中,我们介绍了利用 Fun Local 本地运行、调试函数的方法。但如果仅仅这样简单的介绍,并不能展现 Fun Local 对函数计算开发的巨大效率...

阿里云官方博客
26分钟前
0
0
安卓代码混淆

Proguard是安卓提供的方便开发者对代码和apk进行保护和精简的工具,可在SDK/tools文件夹下找到。 proguard的作用 : 1,代码混淆 2,精简代码,删掉没有用到的代码,减小apk的体积。 使用场景...

whoisliang
31分钟前
1
0
配置Tomcat虚拟主机

12月13日任务 16.4 配置Tomcat监听80端口 16.5/16.6/16.7 配置Tomcat虚拟主机 16.8 Tomcat日志 配置tomcat监听80端口 默认tomcat监听的是8080端口,如果想直接输入ip就访问到网页,就需要进行...

robertt15
36分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部