synchronized 读写同步
synchronized 读写同步 这是一道面试题,很多人也遇到了。 要求:1.读-读 不用线程同步。2.读-写 要求线程同步,写的时候不能读。3.写-写同步。写的时候不能写。 java lock读写锁是好的处理方案。这里不说了。但人家问的是synchronized 读写同步。 假设两个方法,write() ,read();
- read()之间不需要同步,正常的就行。
- read()与write()之间需要同步。
- 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 读写同步的更多相关文章
- Java多线程初学者指南(12):使用Synchronized块同步变量
我们可以通过synchronized块来同步特定的静态或非静态方法.要想实现这种需求必须为这些特性的方法定义一个类变量,然后将这些方法的代码用synchronized块括起来,并将这个类变量作为参数传 ...
- Java多线程初学者指南(10):使用Synchronized关键字同步类方法
要想解决“脏数据”的问题,最简单的方法就是使用synchronized关键字来使run方法同步,代码如下: public synchronized void run() { ... } 从上面的代码可 ...
- 浅谈linux读写同步机制RCU
RCU是linux系统的一种读写同步机制,说到底他也是一种内核同步的手段,本问就RCU概率和实现机制,给出笔者的理解. [RCU概率] 我们先看下内核文档中对RCU的定义: RCU is a sync ...
- java synchronized 线程同步机制详解
Java语言的关键字,当它用来修饰一个方法或者一个代码块的时候,能够保证在同一时刻最多只有一个线程执行该段代码. 一.当两个并发线程访问同一个对象object中的这个synchronized(this ...
- 深入理解synchronized方法同步的是方法还是对象?
一.运用synchronized关键字 首先我们来看看一个多线程中线程不安全的列子 代码如下: 共享数据类: public class NotSynchronizated extends Thread ...
- Java的synchronized的同步代码块和同步方法的区别
synchronized同步方法和同步代码块的区别 同步方法默认使用this或者当前类做为锁. 同步代码块可以选择以什么来加锁,比同步方法更精确,我们可以选择只有会在同步发生同步问题的代码加锁,而并不 ...
- 使用Synchronized块同步变量
我们可以通过synchronized块来同步特定的静态或非静态方法.要想实现这种需求必须为这些特定的方法定义一个类变量,然后将这些方法的代码用synchronized块括起来,并将这个类变量作为参数传 ...
- 使用Synchronized关键字同步类方法
要想解决“脏数据”的问题,最简单的方法就是使用synchronized关键字来使run方法同步,代码如下: public synchronized void run() { } 从上面的代码可以看出, ...
- Java多线程简析——Synchronized(同步锁)、Lock以及线程池
Java多线程 Java中,可运行的程序都是有一个或多个进程组成.进程则是由多个线程组成的.最简单的一个进程,会包括mian线程以及GC线程. 线程的状态 线程状态由以下一张网上图片来说明: 在图中, ...
随机推荐
- 在iPhone开发中实现解压缩gzip
在iPhone开发中实现解压缩gzip是本文要介绍的内容,最近做的一个东西中,需要从网络获取xml文件,但是该文件用了gzip压缩的.搜索一 下有人说gzip压缩的用urlrequest可以自己解压, ...
- CentOS7 SVN基本配置
开机自启指令如下 systemctl enable svnserve.service 对应可执行脚本文件路径 vim /etc/sysconfig/svnserve 查看状态: ps -ef|grep ...
- Shell编程备份数据库
案例: 在/usr/sbin/建立Shell文件 备份后查看目录: 然后进行crontab任务调度: #每天凌晨两点十分调度一次 * * * /usr/sbin/mysql_db.sh
- Java程序员常用的Linux命令01——linux命令基础
1.显示日期的命令date 显示日期: [root@localhost ~]# date 显示年月日: [root@localhost ~]# date '+%Y%m%d' 2.显示日历指令cal 显 ...
- 三种Shell脚本编程中避免SFTP输入密码的方法
最近编程中用到sftp上传文件,且需要用crontab预设定时上传事件.而sftp不同于ftp,没有提供选项如 -i 可以将密码直接编码进程序.使用sftp指令,会自动请求用户输入密码. 总结一下可以 ...
- 【LOJ 6695】天气之子
找规律题的典范? OEIS裸题 考场上让你用 OEIS 吗 题意 link 题解 \(n\le 5\) 打表 \(n\le 10^5\) 发现不能直接求最优解,于是二分答案. 验证答案时,先把前 \( ...
- [uboot] (第三章)uboot流程——uboot-spl代码流程 后续2018版本分析
board_init_f在/u-boot-2018.07-fmxx/arch/arm/mach-fmxx/spl.c中定义 board_init_f之后,和转载的部分有出入: u-boot-2018. ...
- SELinux 对nginx访问目录的影响
centos新装的系统,用yum 安装的nginx . 因用yum 安装的nginx 默认目录在/usr下面. 当SELinux开启时,将会禁止访问设置在其他路径下的地址.比如我设置server 中 ...
- vue 中 弹幕的播放
前言 最近在搞弹幕的问题,小程序上的和vue上的,不想使用插件,于是自己摸索了一下,其实包括 2中弹幕形式 有序和无序的 直接上代码吧 <!-- 弹幕 --> <template v ...
- mysql常用查询命令
转引自:https://www.cnblogs.com/widows/p/7137184.html 常用mysql命令 show variables like 'character_set_clien ...