`
zsnlovewl
  • 浏览: 175436 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

Java synchronized用法搜集

    博客分类:
  • JAVA
阅读更多

 1、synchronized关键字的作用域有二种:

  1)是某个对象实例内,synchronized aMethod(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;

  2)是某个类的范围,synchronized static aStaticMethod{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用。

  2、除了方法前用synchronized关键字,synchronized关键字还可以用于方法中的某个区块中,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/*区块*/},它的作用域是当前对象;

  3、synchronized关键字是不能继承的,也就是说,基类的方法synchronized f(){} 在继承类中并不自动是synchronized f(){},而是变成了f(){}。继承类需要你显式的指定它的某个方法为synchronized方法;

  ----------------------------------------------------------------------------

  java里面synchronized用法

  synchronized的一个简单例子

  public class TextThread

  {

  /**

  * @param args

  */

  public static void main(String[] args)

  {

  // TODO 自动生成方法存根

  TxtThread tt = new TxtThread();

  new Thread(tt).start();

  new Thread(tt).start();

  new Thread(tt).start();

  new Thread(tt).start();

  }

  }

  class TxtThread implements Runnable

  {

  int num = 100;

  String str = new String();

  public void run()

  {

  while (true)

  {

  synchronized(str)

  {

  if (num>0)

  {

  try

  {

  Thread.sleep(10);

  }

  catch(Exception e)

  {

  e.getMessage();

  }

  System.out.println(Thread.currentThread().getName()+ "this is "+ num--);

  }

  }

  }

  }

  }

  上面的例子中为了制造一个时间差,也就是出错的机会,使用了Thread.sleep(10)

  Java对多线程的支持与同步机制深受大家的喜爱,似乎看起来使用了synchronized关键字就可以轻松地解决多线程共享数据同步问题。到底如何?――还得对synchronized关键字的作用进行深入了解才可定论。

  总的说来,synchronized关键字可以作为函数的修饰符,也可作为函数内的语句,也就是平时说的同步方法和同步语句块。如果再细的分类,synchronized可作用于instance变量、object reference(对象引用)、static函数和class literals(类名称字面常量)身上。

  在进一步阐述之前,我们需要明确几点:

  A.无论synchronized关键字加在方法上还是对象上,它取得的锁都是对象,而不是把一段代码或函数当作锁――而且同步方法很可能还会被其他线程的对象访问。

  B.每个对象只有一个锁(lock)与之相关联。

  C.实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。

  接着来讨论synchronized用到不同地方对代码产生的影响:

  假设P1、P2是同一个类的不同对象,这个类中定义了以下几种情况的同步块或同步方法,P1、P2就都可以调用它们。

  1. 把synchronized当作函数修饰符时,示例代码如下:

  Public synchronized void methodAAA()

  {

  //….

  }

  这也就是同步方法,那这时synchronized锁定的是哪个对象呢?它锁定的是调用这个同步方法对象。也就是说,当一个对象P1在不同的线程中执行这个同步方法时,它们之间会形成互斥,达到同步的效果。但是这个对象所属的Class所产生的另一对象P2却可以任意调用这个被加了synchronized关键字的方法。

  上边的示例代码等同于如下代码:

  public void methodAAA()

  {

  synchronized (this)      // (1)

  {

  //…..

  }

  }

  (1)处的this指的是什么呢?它指的就是调用这个方法的对象,如P1。可见同步方法实质是将synchronized作用于object reference。――那个拿到了P1对象锁的线程,才可以调用P1的同步方法,而对P2而言,P1这个锁与它毫不相干,程序也可能在这种情形下摆脱同步机制的控制,造成数据混乱:(

  2.同步块,示例代码如下:

  public void method3(SomeObject so)

  {

  synchronized(so)

  {

  //…..

  }

  }

  这时,锁就是so这个对象,谁拿到这个锁谁就可以运行它所控制的那段代码。当有一个明确的对象作为锁时,就可以这样写程序,但当没有明确的对象作为锁,只是想让一段代码同步时,可以创建一个特殊的instance变量(它得是一个对象)来充当锁:

  class Foo implements Runnable

  {

  private byte[] lock = new byte[0]; // 特殊的instance变量

  Public void methodA()

  {

  synchronized(lock) { //… }

  }

  //…..

  }

  注:零长度的byte数组对象创建起来将比任何对象都经济――查看编译后的字节码:生成零长度的byte[]对象只需3条操作码,而Object lock = new Object()则需要7行操作码。

  3.将synchronized作用于static 函数,示例代码如下:

  Class Foo

  {

  public synchronized static void methodAAA()   // 同步的static 函数

  {

  //….

  }

  public void methodBBB()

  {

  synchronized(Foo.class)   // class literal(类名称字面常量)

  }

  }

  代码中的methodBBB()方法是把class literal作为锁的情况,它和同步的static函数产生的效果是一样的,取得的锁很特别,是当前调用这个方法的对象所属的类(Class,而不再是由这个Class产生的某个具体对象了)。

  记得在《Effective Java》一书中看到过将 Foo.class和 P1.getClass()用于作同步锁还不一样,不能用P1.getClass()来达到锁这个Class的目的。P1指的是由Foo类产生的对象。

  可以推断:如果一个类中定义了一个synchronized的static函数A,也定义了一个synchronized 的instance函数B,那么这个类的同一对象Obj在多线程中分别访问A和B两个方法时,不会构成同步,因为它们的锁都不一样。A方法的锁是Obj这个对象,而B的锁是Obj所属的那个Class。

  小结如下:

  搞清楚synchronized锁定的是哪个对象,就能帮助我们设计更安全的多线程程序。

  还有一些技巧可以让我们对共享资源的同步访问更加安全

  1. 定义private 的instance变量+它的 get方法,而不要定义public/protected的instance变量。如果将变量定义为public,对象在外界可以绕过同步方法的控制而直接取得它,并改动它。这也是JavaBean的标准实现方式之一。

  2. 如果instance变量是一个对象,如数组或ArrayList什么的,那上述方法仍然不安全,因为当外界对象通过get方法拿到这个instance对象的引用后,又将其指向另一个对象,那么这个private变量也就变了,岂不是很危险。 这个时候就需要将get方法也加上synchronized同步,并且,只返回这个private对象的clone()――这样,调用端得到的就是对象副本的引用了。

分享到:
评论

相关推荐

    16.线程的同步机制-synchronized同步方法-多个对象使用多个对象锁.mp4

    在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。

    java学习中收集的有用资料

    6. **多线程**:Java提供了强大的多线程支持,包括Thread类、Runnable接口、同步机制(synchronized关键字、wait()、notify()方法)、线程池等。理解和掌握并发编程是编写高效率程序的关键。 7. **JVM原理**:理解...

    java技术资料收集bibabo

    理解和使用Thread类、Runnable接口以及同步机制(如synchronized关键字、Lock接口)是高级Java编程的关键。 6. **网络编程**:Java的Socket编程允许创建客户端和服务器应用程序,实现网络通信。 7. **反射机制**:...

    java基本组件使用

    JVM通过内存区域(如堆、栈、方法区)和垃圾收集机制来管理程序运行时的内存。理解JVM的工作原理,包括内存模型、类加载机制、性能优化等方面,对于提高Java程序的性能至关重要。 2. 类库与API Java类库包含了大量...

    Java习惯用法总结编程小技巧共14页.pdf.zip

    理解和使用synchronized关键字、Lock接口、ExecutorService等工具可以提高并发性能。 6. **IO流**:Java的IO流系统涵盖了输入输出的各种场景,包括字符流和字节流、缓冲流、转换流等。NIO(New IO)提供非阻塞I/O...

    java学习资料收集库 Java学习资料

    这份"java学习资料收集库"包含了丰富的资源,旨在帮助初学者和有经验的开发者深化对Java语言的理解和应用能力。以下是对这些资源的详细解读: 1. **Java基础知识**: - **语法与结构**:Java的基本语法包括变量、...

    java面试 java书籍

    Java是一种广泛使用的面向对象的编程语言,以其跨平台、高性能和丰富的类库而备受赞誉。在IT行业,尤其是软件开发领域,Java工程师是需求量极大的职位。为了在Java面试中脱颖而出,深入理解Java语言的核心概念和技术...

    java相关提升doc

    3. **java里面synchronized用法.doc**:`synchronized`关键字是Java中的同步控制机制,用于处理多线程环境下的并发问题。文档可能讲解了其基本用法(同步代码块和同步方法)、锁的概念、可见性和有序性保证,以及与...

    Java面试要点(适用于2年以上经验,1年亦可)

    Java 是一种广泛使用的编程语言,涵盖了基础知识、JVM、并发、锁、分布式等领域。以下是Java面试要点的详细知识点总结: 基础篇 1. JVM 内存结构:堆、栈、方法区、直接内存、堆和栈区别 2. Java 内存模型:内存...

    自己收集的Java题库

    这份"自己收集的Java题库"是为教学和自学设计的宝贵资源,包含笔答题和选择题,旨在帮助学生和自学者深入理解Java的核心概念和技术。 笔答题库通常会涵盖更深层次的理解和分析,有助于锻炼读者解决问题的能力和逻辑...

    java多线程知识讲解及练习题

    5. synchronized 和 java.util.concurrent.locks.Lock 的异同 主要相同点:Lock 能完成 synchronized 所实现的所有功能;主要不同点:Lock 有比 synchronized 更精确的线程语义和更好的性能。synchronized 会自动...

    高质量java编程

    6. **多线程**:Java提供了内置的多线程支持,书中介绍了Thread类、Runnable接口,以及同步机制(如synchronized关键字,wait()、notify()和notifyAll()方法)。 7. **反射机制**:反射是Java的高级特性,允许在...

    java笔记java笔试题 java面试题

    11. **JVM**:理解Java虚拟机的工作原理,如类加载机制、内存模型(堆、栈、方法区等)、垃圾收集等。 12. **Java 8及更高版本的新特性**:例如Lambda表达式、函数式接口、Stream API、Optional类等。 在"java...

    华为java培训资料搜集

    这个“华为java培训资料搜集”压缩包,旨在帮助有志于加入华为的Java开发者提升技能,更好地适应公司的工作环境。 1. **Java基础知识**:华为Java培训通常会从基础开始,包括Java语法、数据类型、运算符、控制流程...

    java笔试题(收集了各大公司的笔试题)

    这份"java笔试题(收集了各大公司的笔试题)"资源包含了众多知名企业的题目,可以帮助求职者在准备面试时进行全方位的复习。 1. **Java基础语法**:这部分内容包括变量声明、数据类型、运算符、流程控制语句(如if-...

    java开发java开发

    8. **JVM内存管理**:理解Java虚拟机(JVM)的工作原理,特别是垃圾收集机制,可以帮助优化内存使用和防止内存泄漏。 9. **设计模式**:设计模式是解决常见问题的最佳实践,如单例模式、工厂模式和观察者模式等。...

    java基础学习课件ppt

    8. **多线程**:学习如何创建和管理线程,理解线程同步和互斥,包括synchronized关键字、wait()、notify()方法和Lock接口。 9. **网络编程**:介绍Socket编程,学习如何创建服务器端和客户端,实现数据的发送与接收...

    java解惑java解惑java解惑

    - **方法**:Java中的函数,用于封装可重用的代码。 2. **面向对象编程** - **类与对象**:Java是面向对象的语言,理解类的定义、对象的创建以及它们之间的关系是基础。 - **封装、继承和多态**:这三个面向对象...

    java程序设计课件

    不同于C++需要程序员手动管理内存,Java通过垃圾收集器自动回收不再使用的对象,避免了内存泄漏的问题。理解如何创建对象、对象生命周期以及如何合理使用引用是提高程序效率的关键。 异常处理在Java中也占据重要...

    Java Language Specification(Java编程规范)中英文

    - **自动内存管理**:Java使用垃圾收集器自动回收不再使用的对象,释放内存。 - **引用类型**:强引用、软引用、弱引用和虚引用,分别对应不同的内存管理策略。 7. **多线程**: - **线程的创建与启动**:通过...

Global site tag (gtag.js) - Google Analytics