synchronized 读写同步

这是一道面试题,很多人也遇到了。

要求:1.读-读 不用线程同步。2.读-写 要求线程同步,写的时候不能读。3.写-写同步。写的时候不能写。

java lock读写锁是好的处理方案。这里不说了。但人家问的是synchronized 读写同步。

假设两个方法,write() ,read();
  1. read()之间不需要同步,正常的就行。
  2. read()与write()之间需要同步。
  3. write()之间需要同步。
1.和3.很好理解也很现实。

经过思考:write()必须是同步的,所有对象都要同步。那这里需要设计成静态的。如果不静态的,保证每次同步都是一个锁。
其次 read() 之前要栓查write同步锁,但又没有对应方法可以检查。想到的是 再写一个栓查方法。这个方法与write使用同一个同步锁(设计在同一个类,同时静态)。但这个方法是空的,什么也不做。
所以设计成如下代码:
package test;

public class Test {

    public void read() {

        canRead();
System.out.println(Thread.currentThread().getName() + "-->>begain read");
System.out.println(Thread.currentThread().getName() + "-->>reading");
try {
Thread.sleep(1100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-->>read end");
} public static synchronized void canRead() { } public static synchronized void write() {
System.out.println(Thread.currentThread().getName() + "-->>begain write");
canRead();
System.out.println(Thread.currentThread().getName() + "-->>writing");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "-->>writing end");
return;
} public static void main(String[] args) { Test test = new Test();
Thread t = new Thread(new Runnable() { @Override
public void run() {
while (true) {
test.read();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t.setName("read_thread_1");
t.start(); Thread t1 = new Thread(new Runnable() { @Override
public void run() {
while (true) {
test.read();
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
});
t1.setName("read_thread_2");
t1.start(); Thread t2 = new Thread(new Runnable() { @Override
public void run() {
while (true) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Test.write();
}
}
});
t2.setName("write_thread");
t2.start();
Thread t3 = new Thread(new Runnable() { @Override
public void run() {
while (true) {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
Test.write();
}
}
});
t3.setName("write_thread_2");
t3.start(); } }

运行结果如下,通过结果分析,读线程是穿插的,不存在同步。写线程都是完整执行过程,是同步的。

read_thread_1-->>begain read

read_thread_1-->>reading

read_thread_2-->>begain read

read_thread_2-->>reading

read_thread_1-->>read end

read_thread_2-->>read end

read_thread_1-->>begain read

read_thread_1-->>reading

read_thread_2-->>begain read

read_thread_2-->>reading

read_thread_1-->>read end

read_thread_2-->>read end

write_thread-->>begain write

write_thread-->>writing

write_thread-->>writing end

read_thread_2-->>begain read

read_thread_2-->>reading

read_thread_1-->>begain read

read_thread_1-->>reading

write_thread_2-->>begain write

write_thread_2-->>writing

write_thread_2-->>writing end

read_thread_2-->>read end

read_thread_1-->>read end

read_thread_2-->>begain read

read_thread_2-->>reading

read_thread_1-->>begain read

read_thread_1-->>reading

read_thread_2-->>read end

read_thread_1-->>read end

write_thread-->>begain write

write_thread-->>writing

write_thread-->>writing end

write_thread_2-->>begain write

write_thread_2-->>writing

write_thread_2-->>writing end

read_thread_1-->>begain read

read_thread_1-->>reading

read_thread_2-->>begain read

read_thread_2-->>reading

read_thread_1-->>read end

read_thread_2-->>read end

read_thread_1-->>begain read

read_thread_1-->>reading

read_thread_2-->>begain read

read_thread_2-->>reading

write_thread-->>begain write

write_thread-->>writing

read_thread_1-->>read end

read_thread_2-->>read end

write_thread-->>writing end

write_thread_2-->>begain write

write_thread_2-->>writing

write_thread_2-->>writing end

read_thread_2-->>begain read

read_thread_2-->>reading

read_thread_1-->>begain read

read_thread_1-->>reading

read_thread_2-->>read end

read_thread_1-->>read end

read_thread_2-->>begain read

read_thread_1-->>begain read

read_thread_1-->>reading

read_thread_2-->>reading

write_thread-->>begain write

write_thread-->>writing

这个代码冗余部分是要执行一个空方法,目前还没有想到其它方法,有大牛有好办法可以留言互相学习。

代码 bug :开始写的时候还没有读完的线程。会导致错误。

-----待改进-----------

synchronized 读写同步的更多相关文章

  1. Java多线程初学者指南(12):使用Synchronized块同步变量

    我们可以通过synchronized块来同步特定的静态或非静态方法.要想实现这种需求必须为这些特性的方法定义一个类变量,然后将这些方法的代码用synchronized块括起来,并将这个类变量作为参数传 ...

  2. Java多线程初学者指南(10):使用Synchronized关键字同步类方法

    要想解决“脏数据”的问题,最简单的方法就是使用synchronized关键字来使run方法同步,代码如下: public synchronized void run() { ... } 从上面的代码可 ...

  3. 浅谈linux读写同步机制RCU

    RCU是linux系统的一种读写同步机制,说到底他也是一种内核同步的手段,本问就RCU概率和实现机制,给出笔者的理解. [RCU概率] 我们先看下内核文档中对RCU的定义: RCU is a sync ...

  4. java synchronized 线程同步机制详解

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

  5. 深入理解synchronized方法同步的是方法还是对象?

    一.运用synchronized关键字 首先我们来看看一个多线程中线程不安全的列子 代码如下: 共享数据类: public class NotSynchronizated extends Thread ...

  6. Java的synchronized的同步代码块和同步方法的区别

    synchronized同步方法和同步代码块的区别 同步方法默认使用this或者当前类做为锁. 同步代码块可以选择以什么来加锁,比同步方法更精确,我们可以选择只有会在同步发生同步问题的代码加锁,而并不 ...

  7. 使用Synchronized块同步变量

    我们可以通过synchronized块来同步特定的静态或非静态方法.要想实现这种需求必须为这些特定的方法定义一个类变量,然后将这些方法的代码用synchronized块括起来,并将这个类变量作为参数传 ...

  8. 使用Synchronized关键字同步类方法

    要想解决“脏数据”的问题,最简单的方法就是使用synchronized关键字来使run方法同步,代码如下: public synchronized void run() { } 从上面的代码可以看出, ...

  9. Java多线程简析——Synchronized(同步锁)、Lock以及线程池

    Java多线程 Java中,可运行的程序都是有一个或多个进程组成.进程则是由多个线程组成的.最简单的一个进程,会包括mian线程以及GC线程. 线程的状态 线程状态由以下一张网上图片来说明: 在图中, ...

随机推荐

  1. 详解Wox

    Wox 是一款国产开源免费的软件快捷启动工具,它可以快速搜索并打开你电脑上的程序.文件.或是查词翻译.网站查找等其他操作,同时还支持插件安装. Tips: 如果你需要用到文件的快速搜索.打开功能,需要 ...

  2. jQuery效果--隐藏和显示

    jQuery hide() 和 show() 通过 jQuery,您可以使用 hide() 和 show() 方法来隐藏和显示 HTML 元素: $("#hide").click( ...

  3. 理解js异步编程

    Promise 背景 javascript语言的一大特点就是单线程,在某个特定的时刻只有特定的代码能够被执行,并阻塞其它的代码,也就是说,同一个时间只能做一件事. 怎么做到异步编程?回调函数.直到no ...

  4. Hybrid APP架构设计

    通讯 作为一种跨语言开发模式,通讯层是Hybrid架构首先应该考虑和设计的,往后所有的逻辑都是基于通讯层展开. Native(以Android为例)和H5通讯,基本原理: Android调用H5:通过 ...

  5. git配置ssh秘钥(公钥以及私钥)linux

    本文默认已经安装git,并有github或者gitlab账号 git在linux下安装参考:https://www.cnblogs.com/lz0925/p/10791147.html 在Linux中 ...

  6. symfony2学习笔记——控制器

    //获取get过来的参数 $val = $request->query->get('aaa'); //获取post过来的参数 //$val = $request->request-& ...

  7. shell awk读取文件中的指定行的指定字段

    1.awk功能和实用形式 awk指定读取文件中的某一行的某个字段 awk      可以设置条件来输出文件中m行到n行中每行的指定的k字段,使用格式如下 awk    'NR==m,NR==n {pr ...

  8. kubesphere集群节点扩容

    原有的节点是 : master[123] , node[1234] 新加的节点node5 一.修改配置文件hosts.ini [root@master0 ~]# /conf/hosts.ini [al ...

  9. centos7 Keepalived + Haproxy + MySQL pxc5.6

    拓扑图 应用通过 VIP 连接到 Haproxy,Haproxy 通过http代理分发请求到后端 3 台 MySQL pxc. Keepalived 可以有效防止 Haproxy 单点故障. MySQ ...

  10. 【hiho1715】树的联通问题

    题目大意:给定一棵 1~n 标号的树.Tree[L,R]表示最少需要选择的边的数量使得 L~R 号点两两连通.求: \[ \sum_{L=1}^{n} \sum_{R=L}^{n} \operator ...