Synchronized

1. 将synchronized加在方法上, 即可实现对此方法的同步

public synchronized void deposit(float amt) {
float tmp = amount;
tmp += amt;
try {
Thread.sleep(1);//模拟其它处理所需要的时间,比如刷新数据库等
} catch (InterruptedException e) {
// ignore
}
amount = tmp;
}

同步加锁的是对象,而不是代码, 这时候对于方法所属的类, 如果创建两个不同的对象, 依然可以在两个线程里同时执行此方法

2. 要实现真正的方法上同步,你必须同步一个全局对象或者对类进行同步。下面的代码给出了一个这样的范例。

class Foo extends Thread
{
 private int val;
 public Foo(int v)
 {
  val = v;
 }
 public void printVal(int v)
 {
  synchronized(Foo.class) {
   while(true)
    System.out.println(v);
  }
 }
 public void run()
 {
  printVal(val);
 }
}

注意这里synchronized了Foo.class, 不再对个别的类实例同步而是对类进行同步。对于类Foo而言,它只有唯一的类定义,两个线程在相同的锁上同步,因此只有一个线程可以执行printVal方法。

3. 这个代码也可以通过对公共对象加锁。例如给Foo添加一个静态成员。两个方法都可以同步这个对象而达到线程安全。

class Foo extends Thread
{
 private int val;
 private static Object lock=new Object();
 public Foo(int v)
 {
  val = v;
 }
 public void printVal(int v)
 {
  synchronized(lock) {
   while(true)
    System.out.println(v);
  }
 }
 public void run()
 {
  printVal(val);
 }
}

上面的这个例子比之前给出的例子要好一些, 因为之前加锁是针对类定义的, 一个类只能有一个类定义, 而同步的一般原理是应该尽量减小同步的粒度以到达更好的性能. 这个范例的同步粒度比之前的要小

===

1. synchronized关键字的作用
  a. 当两个并发线程访问同一个对象object中的这个synchronized(this)同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。
  b. 当一个线程访问object的一个synchronized(this)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块。
  c. 当一个线程访问object的一个synchronized(this)同步代码块时,其他线程对object中所有其它synchronized(this)同步代码块的访问将被阻塞。
  d. 第三个例子同样适用其它同步代码块。也就是说,当一个线程访问object的一个synchronized(this)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。
  e. 以上规则对其它对象锁同样适用.

2. synchronized关键字的作用域
  a. 某个对象实例内,synchronized method(){}可以防止多个线程同时访问这个对象的synchronized方法(如果一个对象有多个synchronized方法,只要一个线程访问了其中的一个synchronized方法,其它线程不能同时访问这个对象中任何一个synchronized方法)。这时,不同的对象实例的synchronized方法是不相干扰的。也就是说,其它线程照样可以同时访问相同类的另一个对象实例中的synchronized方法;
  b. 某个类的范围,synchronized static method{}防止多个线程同时访问这个类中的synchronized static 方法。它可以对类的所有对象实例起作用
  c. 方法中的某个区块,表示只对这个区块的资源实行互斥访问。用法是: synchronized(this){/*区块*/},它的作用域是当前对象

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

===

synchronized 关键字,它包括两种用法:synchronized 方法和 synchronized 块。  
1. synchronized 方法:通过在方法声明中加入 synchronized关键字来声明 synchronized 方法。如:  
  public synchronized void accessVal(int newVal);  
  synchronized 方法控制对类成员变量的访问:每个类实例对应一把锁,每个 synchronized 方法都必须获得调用该方法的类实例的锁方能执行,否则所属线程阻塞,方法一旦执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保了同一时刻对于每一个类实例,其所有声明为 synchronized 的成员函数中至多只有一个处于可执行状态(因为至多只有一个能够获得该类实例对应的锁),从而有效避免了类成员变量的访问冲突(只要所有可能访问类成员变量的方法均被声明为 synchronized). 在 Java 中,不光是类实例,每一个类也对应一把锁,这样我们也可将类的静态成员函数声明为 synchronized ,以控制其对类的静态成员变量的访问。
  synchronized 方法的缺陷:若将一个大的方法声明为synchronized 将会大大影响效率,典型地,若将线程类的方法 run() 声明为synchronized ,由于在线程的整个生命期内它一直在运行,因此将导致它对本类任何 synchronized 方法的调用都永远不会成功。当然我们可以通过将访问类成员变量的代码放到专门的方法中,将其声明为 synchronized ,并在主方法中调用来解决这一问题,但是 Java 为我们提供了更好的解决办法,那就是 synchronized 块。
2. synchronized 块:通过 synchronized关键字来声明synchronized 块。语法如下:  
  synchronized(syncObject) {  
    //允许访问控制的代码  
  }  
  synchronized 块是这样一个代码块,其中的代码必须获得对象 syncObject (如前所述,可以是类实例或类)的锁方能执行,具体机制同前所述。由于可以针对任意代码块,且可任意指定上锁的对象,故灵活性较高。

lock(), lockInterruptibly()

lock(), 拿不到lock, 线程就一直block, 忽略线程的interrupt
tryLock(), 拿不拿得到都立即返回
带时间限制的tryLock(), 拿不到lock就等一段时间直至超时

lockInterruptibly()

每个线程都有一个中断标志, 这里分两种情况:

1.线程在sleep, wait, join状态, 此时如果别的进程调用此进程的 interrupt() 方法, 此线程会被唤醒并被要求处理InterruptedException.

2.线程在运行中则不会收到提醒, 但是此线程的中断标志会被设置, 可以通过isInterrupted()查看并作出处理

lockInterruptibly()和上面的第一种情况是一样的, 线程在请求lock并被阻塞时, 如果被interrupt, 则此线程会被唤醒并被要求处理InterruptedException, 并且如果线程已经被interrupt, 再使用lockInterruptibly的时候, 此线程也会被要求处理interruptedException

Lock的中断和非中断加锁模式的区别在于: 线程尝试获取锁操作失败后,在等待过程中,如果该线程被其他线程中断了,它是如何响应中断请求的.

lock方法会忽略中断请求,继续获取锁直到成功;而lockInterruptibly则直接抛出中断异常来立即响应中断,由上层调用者处理中断。

lock()适用于锁获取操作不受中断影响的情况,此时可以忽略中断请求正常执行加锁操作,因为该操作仅仅记录了中断状态(通过Thread.currentThread().interrupt()操作,只是恢复了中断状态为true,并没有对中断进行响应)。

如果要求被中断线程不能参与锁的竞争操作,则此时应该使用lockInterruptibly方法,一旦检测到中断请求,立即返回不再参与锁的竞争并且取消锁获取操作(即finally中的cancelAcquire操作)

Java synchronized的更多相关文章

  1. Java Synchronized Blocks

    From http://tutorials.jenkov.com/java-concurrency/synchronized.html By Jakob Jenkov   A Java synchro ...

  2. java synchronized(一)

    java synchronized主要用于控制线程同步,中间有很多小的细节,知识,这里我简单的整理一下,做个记录.主要用于方法和代码块的控制 先说说方法控制 模拟银行存款和取款,创建一个Account ...

  3. java synchronized使用

    java synchronized 基本上,所有并发的模式在解决线程冲突问题的时候,都是采用序列化共享资源的方案.这意味着在给定时刻只允许一个任务访问该资源.这个一般通过在代码上加一条锁语句实现,因为 ...

  4. Java synchronized 详解

    Java synchronized 详解 Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 1.当两个并发线程访问同一个对象object ...

  5. Java Synchronized 关键字

    本文内容 Synchronized 关键字 示例 Synchronized 方法 内部锁(Intrinsic Locks)和 Synchronization 参考资料 下载 Demo Synchron ...

  6. Java synchronized 关键字详解

    Java synchronized 关键字详解 前置技能点 进程和线程的概念 线程创建方式 线程的状态状态转换 线程安全的概念 synchronized 关键字的几种用法 修饰非静态成员方法 sync ...

  7. Java synchronized对象级别与类级别的同步锁

    Java synchronized 关键字 可以将一个代码块或一个方法标记为同步代码块.同步代码块是指同一时间只能有一个线程执行的代码,并且执行该代码的线程持有同步锁.synchronized关键字可 ...

  8. java synchronized详解

    Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchronized(this ...

  9. Java synchronized指南

    在多线程程序中,同步修饰符用来控制对临界区代码的访问.其中一种方式是用synchronized关键字来保证代码的线程安全性.在Java中,synchronized修饰的代码块或方法不会被多个线程并发访 ...

随机推荐

  1. AndroidAnnotations简单示例

    @EActivity(R.layout.activity_main) public class MainActivity extends Activity { @ViewById(R.id.textV ...

  2. 【C语言】C语言函数

    目录: 1. [函数注意点] 2. [函数目的] 3. [函数格式] 4. [函数定义前需明确的条件] 5. [函数的形参.实参] 6. [函数返回值注意点] 7. [为什么要return] 8. [ ...

  3. iOS开源项目MobileProject功能点介绍

    一:MobileProject简介 MobileProject项目是一个以MVC模式搭建的开源功能集合,基于Objective-C上面进行编写,意在解决新项目对于常见功能模块的重复开发,MobileP ...

  4. View的事件体系

    View的滑动 实现手段 优点 缺点 备注 scrollTo/scrollBy 使用简单 只能滑动view的内容,并不会滑动view本身. 且内容超出view本身的布局范围部分的不会显示 不适合有交互 ...

  5. 使用Android Annotations开发

    使用Android Annotations框架gradle配置1.修改Module下的build.gradle apply plugin: 'com.android.application' appl ...

  6. 写在复习MVC后

    MVC的一些 今天把MVC复习了下,包括官方文档以及各种中文博客. 官方文档里面最能说明的问题的图片,相对于传统的MVC,苹果分离了View和Model之间的通信,实现了更好的复用性.我觉得MVC更 ...

  7. Cross-Origin Resource Sharing协议介绍

    传统的Ajax请求只能获取在同一个域名下面的资源,但是HTML5打破了这个限制,允许Ajax发起跨域的请求.浏览器是可以发起跨域请求的,比如你可以外链一个外域的图片或者脚本.但是Javascript脚 ...

  8. spring 事务管理方式及配置

    1.Spring声明式事务配置的五种方式 前段时间对Spring的事务配置做了比较深入的研究,在此之前对Spring的事务配置虽说也配置过,但是一直没有一个清楚的认识.通过这次的学习发觉Spring的 ...

  9. js 求时间差

    var date1=new Date();  //开始时间 var date2=new Date();    //结束时间 var date3=date2.getTime()-date1.getTim ...

  10. od

    $od [-t type]查看非文本文件 a 使用默认字符输出 c 使用ASC II字符输出 d[size] 使用十进制来输出数据,每个整数占用size byte o ..八 x ..十六 f ..浮 ...