Java中的线程同步
Java 中的线程同步问题:
1. 线程同步:
对于访问同一份资源的多个线程之间, 来进行协调的这个东西.
2. 同步方法:
当某个对象调用了同步方法时, 该对象上的其它同步方法必须等待该同步方法执行完毕后, 才能被执行.
3. 同步块:
通常将共享资源的操作放置在 synchronized 定义的区域内, 这样当其它线程也获取到这个锁时, 必须等待锁被释放, 才能进入该区域.
Demo_1:
- class Timer {
- private static int num = 0;
- public void add(String name) {
- num++;
- try {
- Thread.sleep(100); // 即使不写 Thread.sleep(100), 这个结果可能是对的,也有可能是错的, 不确定. 中间还是有可能被打断.
- } catch (InterruptedException e) {
- }
- System.out.println(name+", 你是第 "+num+"个使用timer的线程");
- }
- }
- class TestSync implements Runnable {
- Timer timer = new Timer();
- public static void main(String[] args) {
- TestSync test = new TestSync();
- Thread t1 = new Thread(test);
- Thread t2 = new Thread(test);
- t1.setName("t1");
- t2.setName("t2");
- t1.start();
- t2.start();
- }
- @Override
- public void run() {
- timer.add(Thread.currentThread().getName());
- }
- }
会出现的运行结果:
t1, 你是第 2个使用timer的线程
t2, 你是第 2个使用timer的线程
原因:这个线程在执行 add()方法的时候, 被另外一个线程给打断了.
解决办法:
num++;
try {Thread.sleep(100);
} catch (InterruptedException e) {}
上面这几句话, 应该作为一个原子性的输出, 你不应该在中途打断.
第一种解决办法:采用同步块, 如 Demo_2
Demo_2:
- class Timer {
- private static int num = 0;
- public void add(String name) {
- synchronized(this){ // 同步块
- num++;
- try {Thread.sleep(100);
- } catch (InterruptedException e) {}
- System.out.println(name+", 你是第 "+num+"个使用timer的线程");
- }
- }
- }
- class TestSync implements Runnable {
- Timer timer = new Timer();
- public static void main(String[] args) {
- TestSync test = new TestSync();
- Thread t1 = new Thread(test);
- Thread t2 = new Thread(test);
- t1.setName("t1");
- t2.setName("t2");
- t1.start();
- t2.start();
- }
- @Override
- public void run() {
- timer.add(Thread.currentThread().getName());
- }
- }
- // 运行结果如下:
- // t1, 你是第 1个使用timer的线程
- // t2, 你是第 2个使用timer的线程
【注】:既然锁定了当前对象了, 那么这个 num 也就锁定了, 它里面的成员变量当然也锁定(互斥锁).
【注】:锁定当前对象:这执行后面的大括号里面的语句的过程中, 一个线程的执行过程中, 不会被另外一个线程锁打断.
一旦某个线程已经进入到锁定的区域当中, 那么你放心, 不可能有另外一个线程也在里面(锁的机制).
第二种解决办法:采用同步块, 如 Demo_3
Demo_3:
- class Timer {
- private static int num = 0;
- public synchronized void add(String name) { //同步方法
- num++;
- try {Thread.sleep(100);
- } catch (InterruptedException e) {}
- System.out.println(name+", 你是第 "+num+"个使用timer的线程");
- }
- }
- class TestSync implements Runnable {
- Timer timer = new Timer();
- public static void main(String[] args) {
- TestSync test = new TestSync();
- Thread t1 = new Thread(test);
- Thread t2 = new Thread(test);
- t1.setName("t1");
- t2.setName("t2");
- t1.start();
- t2.start();
- }
- @Override
- public void run() {
- timer.add(Thread.currentThread().getName());
- }
- }
- // 运行结果如下:
- // t1, 你是第 1个使用timer的线程
- // t2, 你是第 2个使用timer的线程
分析 Demo_3 的执行过程:
t1 开始执行, 调用 add() 方法, num++, 然后 t1 睡着了, 睡着了也没关系, t1 睡着也抱着那把锁.
别人(t2)也进不来, 你必须等它执行完了, 你才可以继续执行.
睡着了, 也不放开那把锁, 你也没办法.
4. 线程同步总结:
4.1. 在 Java 语言中, 引入了对象互斥锁的概念, 保证共享数据操作的完整性. 每个对象都对应于一个可称为"互斥锁"的标记,
这个标记保证在任一时刻, 只有一个线程访问该对象.
4.2. 关键字 synchronized 与对象的互斥锁联系. 当某个对象用 synchronized 来修饰时, 表明该对象在任一时刻只能由一个线程访问.
Java中的线程同步的更多相关文章
- java中实现线程同步
为何要使用同步? java允许多线程并发控制,当多个线程同时操作一个可共享的资源变量时(如数据的增删改查), 将会导致数据不准确,相互之间产生冲突,因此加入同步锁以避免在该线程没有完成操作之前,被其他 ...
- Java中处理线程同步
引自:http://blog.csdn.net/aaa1117a8w5s6d/article/details/8295527和http://m.blog.csdn.net/blog/undoner/1 ...
- Java中实现线程同步的三种方法
实现同步的三种方法 多线程共享数据时,会发生线程不安全的情况,多线程共享数据必须同步. 实现同步的三种方法: 使用同步代码块 使用同步方法 使用互斥锁ReetrantLock(更灵活的代码控制) 代码 ...
- Java中的线程同步机制
一.首先为什么线程需要同步? 1.多线程安全问题的原因 A:有多线程环境 B:有共享数据 C:有多条语句操作共享数据 2. //未完待续后面会继续更新
- 浅谈利用同步机制解决Java中的线程安全问题
我们知道大多数程序都不会是单线程程序,单线程程序的功能非常有限,我们假设一下所有的程序都是单线程程序,那么会带来怎样的结果呢?假如淘宝是单线程程序,一直都只能一个一个用户去访问,你要在网上买东西还得等 ...
- 关于Java中的线程安全(线程同步)
java中的线程安全是什么: 就是线程同步的意思,就是当一个程序对一个线程安全的方法或者语句进行访问的时候,其他的不能再对他进行操作了,必须等到这次访问结束以后才能对这个线程安全的方法进行访问 什么叫 ...
- Java中的线程Thread总结
首先来看一张图,下面这张图很清晰的说明了线程的状态与Thread中的各个方法之间的关系,很经典的! 在Java中创建线程有两种方法:使用Thread类和使用Runnable接口. 要注意的是Threa ...
- 关于Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇高质量的博文)
Java多线程的线程同步和线程通信的一些小问题(顺便分享几篇质量高的博文) 前言:在学习多线程时,遇到了一些问题,这里我将这些问题都分享出来,同时也分享了几篇其他博客主的博客,并且将我个人的理解也分享 ...
- Java多线程与线程同步
六.多线程,线程,同步 ①概念: 并行:指两个或多个在时间同一时刻发生(同时发生) 并发:指两个或多个事件在同一时间段内发生 具体概念: 在操作系统中,安装了多个程序,并发指的是在一段时间内宏观上有多 ...
随机推荐
- jQuery DOM/属性/CSS操作
jQuery DOM 操作 创建元素 只需要把DOM字符串传入$方法即可返回一个 jQuery 对象 var obj = $('<div class="test">&l ...
- H5新增的标签以及改良的标签
1>OL标签的改良 start type reversed:翻转排序 2>datalist标签自动补全的使用 3>progress标签的使用:进度条 4>meter标签的应用 ...
- sass的嵌套
sass的嵌套包括两种: 1.选择器的嵌套.(最常用到) 指的是在一个选择器中嵌套另一个选择器来实现继承,从而增强了sass文件的结构性和可读性. 在选择器嵌套中,可以使用&表示父元素选择器 ...
- html5 video获取当前时间和视频总时间长度
html: <video id="video-active" class="video-active" width="640" hei ...
- MongoDB 4.0.6 Manual
General mongod options: -v [ --verbose ] [=arg(=v)] be more verbose (include multiple times for more ...
- php 将富文本编辑后的内容取出
背景:项目中用了富文本编辑器,讲写完的内容存入了数据库,但是取出的时候因为有些展示地方并不需要样式,只想获取到内容,所以需要将带了html编码的信息解析出来. 原始信息如下 [task_desc] = ...
- 前端页面加载速度优化---Ngnix之GZIP压缩
gzip on; #开启Gzip gzip_static on;#是否开启gzip静态资源 #nginx对于静态文件的处理模块,该模块可以读取预先压缩的gz文件,这样可以减少每次请求进行gzip压缩的 ...
- OracleLinux上安装Oracle11g图解
磨砺技术珠矶,践行数据之道,追求卓越价值 回到上一级页面: PostgreSQL杂记页 回到顶级页面:PostgreSQL索引页 [作者 高健@博客园 luckyjackgao@gmail. ...
- 2212: [Poi2011]Tree Rotations
2212: [Poi2011]Tree Rotations https://www.lydsy.com/JudgeOnline/problem.php?id=2212 分析: 线段树合并. 首先对每个 ...
- 必读的 Android 文章
必读的 Android 文章 掘金官方 关注 2017.06.07 13:58* 字数 25218 阅读 8782评论 2喜欢 218 写给 Android 开发者的混淆使用手册 - Android ...