java核心知识点学习----多线程并发之线程同步
1.什么是线程同步?
多线程编程是很有趣的事情,它很容易出现"错误情况",这种情况不是由编码造成的,它是由系统的线程调度造成的,当使用多个线程来访问同一个数据时,很容易出现"偶然情况",出现线程安全问题.
线程安全问题最常见的就是银行取钱问题,铁路售票问题,必须保证甲方在操作数据时候,己方不会影响甲方.类似于公共厕所,一个人占一个坑.
2.下面的例子,将说明为什么要保证线程安全?
package com.amos.concurrent;
/**
* @ClassName: ThreadSynchronizedTest
* @Description: 多线程并发之线程同步
* @author: amosli
* @email:hi_amos@outlook.com
* @date Apr 20, 2014 2:44:29 PM
*/
public class ThreadSynchronizedTest {
public static void main(String[] args) {
new ThreadSynchronizedTest().init();
} private void init() {
final OutPuter outPuter = new OutPuter();
//新建一个线程A
new Thread(new Runnable() {
public void run() {
while (true) {
//休息10ms
try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
outPuter.output("hi_amos");//输出
}
}
}).start();
//线程B
new Thread(new Runnable() {
public void run() {
while (true) {
try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
outPuter.output("amosli");
}
}
}).start();
} class OutPuter {
//输出name,逐个字节读取,并输出
public void output(String name) {
int length = name.length();
synchronized (name) {
for (int i = 0; i < length; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
}
输出结果如下图所示:
在多次执行上面的代码后就会发现出现问题了,这是因为线程A和线程B在执行output方法时,系统调度出现了问题,导致了上面的问题,这种情况出现的概率相对较小,但这种小概率的事件也是要解决的.下面将介绍如何解决这种问题.
3.解决方法1--同步代码块
只需要将上面的方法加上synchronized关键字即可
public void output2(String name) {
int length = name.length();
synchronized (this) {
for (int i = 0; i < length; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
在要多次访问的代码块前加上synchronized关键字,即表示加上排队系统,线程A只有等线程B执行完了才能访问同一个代码块.
这里要注意this,this表示的是当前对象,这里this也可以用Outputer.class代替.
4.解决方法2--同步方法
public synchronized void output(String name) {
int length = name.length();
for (int i = 0; i < length; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
同步方法,即是在要多次访问的方法前面加上synchronized关键字.
注意:
1.synchronized关键字可以修饰方法,代码块,但不能修饰构造器,属性等;
2.同时synchronized关键字最好一个方法中只用一次,否则可能造成死锁.
3.任何时刻只能有一个线程可以获得对同步监视器的锁定,当同步代码块执行完成后,该线程会释放对该同步监视器的锁定.
上面的代码可以改写如下:
package com.amos.concurrent; /**
* @ClassName: ThreadSynchronizedTest
* @Description: 多线程并发之线程安全
* @author: amosli
* @email:hi_amos@outlook.com
* @date Apr 20, 2014 2:44:29 PM
*/
public class ThreadSynchronizedTest {
public static void main(String[] args) {
new ThreadSynchronizedTest().init();
} private void init() {
final OutPuter outPuter = new OutPuter();
//新建一个线程
new Thread(new Runnable() {
public void run() {
while (true) {
//休息10ms
try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
outPuter.output("hi_amos");//输出
}
}
}).start(); new Thread(new Runnable() {
public void run() {
while (true) {
try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}
outPuter.output("amosli");
}
}
}).start();
} static class OutPuter {
//输出name,逐个字节读取,并输出
public synchronized void output(String name) {
int length = name.length();
for (int i = 0; i < length; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
public void output2(String name) {
int length = name.length();
synchronized (OutPuter.class) {
for (int i = 0; i < length; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
public synchronized static void output3(String name) {
int length = name.length();
for (int i = 0; i < length; i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}
java核心知识点学习----多线程并发之线程同步的更多相关文章
- Java核心知识点学习----多线程并发之线程间的通信,notify,wait
1.需求: 子线程循环10次,主线程循环100次,这样间隔循环50次. 2.实现: package com.amos.concurrent; /** * @ClassName: ThreadSynch ...
- Java核心知识点学习----多线程中的阻塞队列,ArrayBlockingQueue介绍
1.什么是阻塞队列? 所谓队列,遵循的是先进先出原则(FIFO),阻塞队列,即是数据共享时,A在写数据时,B想读同一数据,那么就将发生阻塞了. 看一下线程的四种状态,首先是新创建一个线程,然后,通过s ...
- Java核心知识点学习----使用Condition控制线程通信
一.需求 实现线程间的通信,主线程循环3次后,子线程2循环2次,子线程3循环3次,然后主线程接着循环3次,如此循环3次. 即:A->B->C---A->B->C---A-> ...
- Java核心知识点学习----多线程 倒计时记数器CountDownLatch和数据交换的Exchanger
本文将要介绍的内容都是Java5中的新特性,一个是倒计时记数器---CountDownLatch,另一个是用于线程间数据交换的Exchanger. 一.CountDownLatch 1.什么是Coun ...
- java核心知识点学习----多线程间的数据共享和对象独立,ThreadLocal详解
线程内的数据共享与对象独立,举例:张三给李四转钱,开启A线程去执行转钱这个动作,刚好同时王五给赵六转钱,开启B线程去执行转钱,因为是调用的同样一个动作或者说对象,所以如果不能保证线程间的对象独立,那么 ...
- java核心知识点学习----多线程间的数据共享的几种实现方式比较
需求:设计4个线程,其中两个线程每次对j增加1,另外两个线程对j减少1. 实现数据共享的几种方式比较: 1.使用同一个runnable对象 如果每个线程执行的代码相同,那么可以使用同一个runnabl ...
- Java核心知识点学习----线程中如何创建锁和使用锁 Lock,设计一个缓存系统
理论知识很枯燥,但这些都是基本功,学完可能会忘,但等用的时候,会发觉之前的学习是非常有意义的,学习线程就是这样子的. 1.如何创建锁? Lock lock = new ReentrantLock(); ...
- Java核心知识点学习----线程同步工具类,CyclicBarrier学习
线程同步工具类,CyclicBarrier日常开发较少涉及,这里只举一个例子,以做备注.N个人一块出去玩,相约去两个地方,CyclicBarrier的主要作用是等待所有人都汇合了,才往下一站出发. 1 ...
- Java核心知识点学习----线程中的Semaphore学习,公共厕所排队策略
1.什么是Semaphore? A counting semaphore. Conceptually, a semaphore maintains a set of permits. Each acq ...
随机推荐
- Java注释Override、Deprecated、SuppressWarnings详解(过时方法,即将删除的方法或成员变量)
Override 这个注释的作用是标识某一个方法是否覆盖了它的父类的方法.那么为什么要标识呢?让我们来看看如果不用Override标识会发生什么事情. Deprecated 这个注释是一个标记注释.所 ...
- OC基础—多态(超级简单)
前言: oc中的指针类型变量有两个:一个是编译时类型,一个是运行时类型,编译时类型由声明该变量是使用的类型决定,运行时类型由实际赋给该变量的对象决定.如果编译时类型和运行时类型不一致,就有可能出现多态 ...
- bower安装使用入门详情
bower安装使用入门详情 bower自定义安装:安装bower需要先安装node,npm,git全局安装bower,命令:npm install -g bower进入项目目录下,新建文件1.tx ...
- ios 开发小技巧一
对于UITableViewCell中的textField/textView,你肯定想让它编辑时可以把所在行滚动到键盘上方.如果你的VC是UITableViewController或者子类,那么只要在o ...
- iOS-浅谈runtime运行时机制
一.首先,从 runtime.h头文件中找到对 class 与 object 的定义 /// An opaque type that represents an Objective-C cla ...
- [HTML] CSS3 文本效果
CSS3 文本效果 CSS3中包含几个新的文本特征. 在本章中您将了解以下文本属性: text-shadow word-wrap 浏览器支持
- [ActionScript 3.0] AS3.0 对象在矩形范围随机运动
package com.views { import flash.display.Bitmap; import flash.display.MovieClip; import flash.displa ...
- Functional testing - python, selenium and django
Functional testing - python selenium django - Source Code : from selenium import webdriverfrom sele ...
- ES6中的Class
对于javascript来说,类是一种可选(而不是必须)的设计模式,而且在JavaScript这样的[[Prototype]] 语言中实现类是很蹩脚的. 这种蹩脚的感觉不只是来源于语法,虽然语法是很重 ...
- 第一波实习的前端笔记(2)——js.md
1.如何解决移动端点透问题? $('xx').on('touchend', function(event){ event.preventDefault(); }) 但是,存在滑动页面会触发问题.期待更 ...