对象的方法中一旦加入synchronized修饰,则任何时刻只能有一个线程访问synchronized修饰的方法。假设有个数据对象拥有写方法与读方法,多线程环境中要想保证数据的安全,需对该对象的读写方法都要加入 synchronized同步块。这样任何线程在写入时,其它线程无法读取与改变数据;如果有线程在读取时,其他线程也无法读取或写入。这种方式在写入操作远大于读操作时,问题不大,而当读取远远大于写入时,会造成性能瓶颈,因为此种情况下读取操作是可以同时进行的,而加锁操作限制了数据的并发读取。

ReadWriteLock解决了这个问题,当写操作时,其他线程无法读取或写入数据,而当读操作时,其它线程无法写入数据,但却可以读取数据 。

  1. public class ReadWriteLockDemo {
  2. static SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  3. public static void main(String[] args) {
  4. Data data = new Data();
  5. Worker t1 = new Worker(data,true);
  6. Worker t2 = new Worker(data,true);
  7. t1.start();
  8. t2.start();
  9. }
  10. static class Worker extends Thread {
  11. Data data;
  12. boolean read;
  13. public Worker(Data data, boolean read) {
  14. this.data = data;
  15. this.read = read;
  16. }
  17. public void run() {
  18. if (read)
  19. data.get();
  20. else
  21. data.set();
  22. }
  23. }
  24. static class Data {
  25. ReadWriteLock lock = new ReentrantReadWriteLock();
  26. Lock read = lock.readLock();
  27. Lock write = lock.writeLock();
  28. public  void set() {
  29. write.lock();
  30. System.out.println(Thread.currentThread().hashCode()
  31. + " set:begin " + sdf.format(new Date()));
  32. try {
  33. Thread.sleep(5000);
  34. //
  35. } catch (Exception e) {
  36. } finally {
  37. System.out.println(Thread.currentThread().hashCode() + " set:end "
  38. + sdf.format(new Date()));
  39. write.unlock();
  40. }
  41. }
  42. public  int get() {
  43. read.lock();
  44. System.out.println(Thread.currentThread().hashCode()
  45. + " get :begin " + sdf.format(new Date()));
  46. try {
  47. Thread.sleep(5000);
  48. //
  49. } catch (Exception e) {
  50. } finally {
  51. System.out.println(Thread.currentThread().hashCode() + " get :end "
  52. + sdf.format(new Date()));
  53. read.unlock();
  54. }
  55. return 1;
  56. }
  57. }
  58. }

两个线程均是读线程,结果如下

22474382 get :begin 2011-04-16 18:26:13
4699264 get :begin 2011-04-16 18:26:13
22474382 get :end 2011-04-16 18:26:18
4699264 get :end 2011-04-16 18:26:18

两读线程均可同时读取数据,下面看一个是读线程,一个写线程的情况

Data data = new Data();
  Worker t1 = new Worker(data,false);
  Worker t2 = new Worker(data,true);
  
  t2.start();
  Thread.sleep(100);
  t1.start();

先启动读取线程,再启动写入线程,看结果

14718739 get :begin 2011-04-16 18:54:46
14718739 get :end 2011-04-16 18:54:51
14737862 set:begin 2011-04-16 18:54:51
14737862 set:end 2011-04-16 18:54:56

可以看到读取线程工作时,写入线程是不能访问数据的

java同一个类不同方法间的同步的更多相关文章

  1. Java并发之线程间的同步协作与通信协作

    1,Monitor监视器与syncrhoized实现原理 1.1:Monitor Monitor是一个同步工具,相当于操作系统中的互斥量(mutex),即值为1的信号量. 它内置与每一个Object对 ...

  2. Java 同一个类的不同实例对象竟然可以相互访问各自的private成员

    如题,在看String源码的某个函数时,发现了这个操作是被允许的,而且可以直接改变private字段(不是final按理是可以改变),这与之前的理解有点相背. 接下来试图整理下Google来的结论: ...

  3. java同一个类中,构造器如何调用另一个重载的构造器?

    构造器里面调用其它构造器,格式方法如下:1.使用this调用另一个重载构造器,只能在构造器中使用:2.必须写在构造器执行体的第一行语句: 示例如下: import static java.lang.S ...

  4. 《同一个类中不同方法之间的调用相关问题(省略的类名或者this)》

    //同一个类中不同方法之间的调用相关问题(省略的类名或者this) class A { public void B() { System.out.println("b方法运行"); ...

  5. java中方法内可以调用同一个类中的方法

    在同一个类中,java的普通方法的相互调用,可以使用this+点号+方法名,也可省略this+点号,java编 译器会自动补上.

  6. Java中同一个类中不同的synchronized方法是否可以并发执行?

    答案是: 不可以,因为都是获取到对象本身的锁. 多个线程访问同一个类的synchronized方法时, 都是串行执行的 ! 就算有多个cpu也不例外 ! synchronized方法使用了类java的 ...

  7. Java多线程(三) 多线程间的基本通信

    多条线程在操作同一份数据的时候,一般需要程序去控制好变量.在多条线程同时运行的前提下控制变量,涉及到线程通信及变量保护等. 本博文主要总结:①线程是如何通信  ②如何保护线程变量 1.Java里的线程 ...

  8. Java的类演进过程

    1.从面向过程到面向对象 在大家最熟悉的C语言中,如果要定义一个复杂的数据类型就用结构体(Struct)来实现,而为结构体的每个操作都定义一个函数,这个函数与结构体本身的定义没有任何关系.程序的重心集 ...

  9. Java并发——线程安全、线程同步、线程通信

    线程安全 进程间"共享"对象 多个“写”线程同时访问对象. 例:Timer实例的num成员,即add()方法是用的次数.即Timer实例是资源对象. class TestSync ...

随机推荐

  1. Noi2011 阿狸的打字机

    ..] of longint; e,q,fa,ps,pt,fail,ans:..] of longint; trie:..,..] of longint; c:..] of longint; s:.. ...

  2. 当想mysql某插入有某字段设置了unique且和之前相同时,会报错,并停止运行

  3. Java面向对象基础知识汇总

    OOP:Orient Object Programe AOP:Aspect Orient Programe 封装:Encapsulation 继承:Inheritance 多态:Polymorphmi ...

  4. BZOJ 2743 树状数组

    不能用分块. #include <bits/stdc++.h> using namespace std; ; struct Info{int l,r,Id;}Q[Maxn]; int a[ ...

  5. linux中模块的构建,传参,和printk函数的简单使用

    静态编译,动态加载应用想访问内核需要通过系统调用 驱动:1.模块(打包,加入内核)2.内核机制3.操作硬件 在Kconfig里面配置menuconfig的时候,不同的类型会在图形化界面的终端显示不用的 ...

  6. GCD: 基本概念和Dispatch Queue 【转】

    什么是GCD? Grand Central Dispatch或者GCD,是一套低层API,提供了一种新的方法来进行并发程序编写.从基本功能上讲,GCD有点像 NSOperationQueue,他们都允 ...

  7. jquery.easyui代码详解,和遇到的问题,提供大家在使用的时候少走弯路(一)

    初次使用jquery.easyui这个东东,虽然简单,但还是很费力的去研究了一下使用,在使用过程中遇到的问题,下面代码会详细的注释到 引用的文件jquery.min.js              j ...

  8. 莱卡旗下旗下首台全片幅无反相机 Leica SL 抵港,吐槽下

    http://cn.engadget.com/2015/11/18/leica-sl-hk-hands-on/#continued 单机+单镜头=7.5W¥,如果再来个定焦共10W¥+:有心杀贼,无力 ...

  9. 记一些之前忘记积累的问题(fiddler 学习、XP系统不能上网、XP不能装fiddler、注册表快速找到)

    记一些之前忘记积累的问题: fiddler学习:http://www.cnblogs.com/kingwolf_JavaScript/archive/2012/11/07/FiddlerUI.html ...

  10. Spring任务调度器之Task的使用

    Spring Task提供两种方式进行配置,正如大家所想吧,还是一种是annotation(标注),而另外一种就是XML配置了.但其实这里我觉得比较尴尬,因为任务调度这样的需求,通常改动都是比较多的, ...