文档章节

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

丈量大地
 丈量大地
发布于 2014/06/11 14:11
字数 1217
阅读 125
收藏 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
JVM到底是怎么处理锁的?怎么不让我阻塞呢?

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

Java大蜗牛
07/15
0
0
理解 java 中的 synchronized 关键字

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

大数据之路
2012/10/27
0
0
Java 多线程编程 — 锁优化2

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

晨猫
04/26
0
0
Java多线程学习(四)等待/通知(wait/notify)机制

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

一只蜗牛呀
04/16
0
0

没有更多内容

加载失败,请刷新页面

加载更多

37. Sudoku Solver

Description tags: backtrack,hash table difficulty: hard Write a program to solve a Sudoku puzzle by filling the empty cells.A sudoku solution must satisfy all of the following......

52iSilence7
17分钟前
0
0
磁盘格式化、磁盘挂载和手动增加swap空间

9月26日任务 4.5/4.6 磁盘格式化 4.7/4.8 磁盘挂载 4.9 手动增加swap空间 4.5/4.6 磁盘格式化 #查看Linux所支持的文件格式 [root@zgxlinux-01 ~]# cat /etc/filesystems xfs...

zgxlinux
28分钟前
0
0
intellij idea中,鼠标拖动选择的是一块矩形区域

点“编辑”-->“列选择模式” 或者 按 Shift+Alt+Insert

hengbao5
30分钟前
0
0
中文地址

火力全開
45分钟前
0
0
71:循环之for、while、break、continue、exit

1、for循环语法: for 变量名 in 条件;do......;done 1:案例1:求1加到100的和: [root@localhost_02 for]# vim for1.sh #!/bin/bashsum=0for i in `seq 1 100`do sum=$[$sum...

芬野de博客
48分钟前
0
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部