线程安全,syncronized 用法
1,为什么有线程安全问题?
当多个线程同时共享同一个全局变量或静态变量,做写的操作时,可能会发生数据冲突问题,也就是线程安全问题。但是做读操作是不会发生数据冲突问题。
public class TrainThread implements Runnable {
// 定义初始化票100张
private int ticketCount = 100;
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
while (ticketCount > 0) {
System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketCount + 1 + "张票"));
ticketCount--;
}
}
}
public class App {
public static void main(String[] args) throws InterruptedException {
TrainThread trainThread = new TrainThread();
//模拟了两个线程,必须都用同一个Runnable 的子类对象,才能叫 实现资源的共享
Thread thread1 = new Thread(trainThread);
Thread thread2 = new Thread(trainThread);
thread1.start();
thread2.start();
}
}
可能出现的情况:同时卖了某一张票
Thread-1卖出了第1张票
Thread-1卖出了第2张票
Thread-0卖出了第1张票
Thread-0卖出了第4张票
Thread-1卖出了第3张票
Thread-1卖出了第6张票
问:为什么使用线程同步或使用锁能解决线程安全问题呢?
答:将可能会发生数据冲突问题(线程不安全问题),只能让当前一个线程进行执行。代码执行完成后释放锁,让后才能让其他线程进行执行。这样的话就可以解决线程不安全问题。
问:什么是多线程之间同步?
答:当多个线程共享同一个资源,不会受到其他线程的干扰
2, 实现线程同步,syncronized 的用法
解决一:
锁对象
syncronized 同步代码块:就是将可能会发生线程安全问题的代码,给包括起来。
synchronized(同一个数据){
可能会发生线程冲突问题
}
public class TrainThread implements Runnable {
// 定义初始化票100张
private int ticketCount = 100;
//定义了一个共享的对象
private Object obj = new Object();
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (obj) {
while (ticketCount > 0) {
System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketCount + 1 + "张票"));
ticketCount--;
}
}
}
}
解决二:
同步函数,
在方法上修饰synchronized 称为同步函数
锁方法
public class TrainThread implements Runnable {
// 定义初始化票100张
private int ticketCount = 100;
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
sale();
}
private synchronized void sale() {
while (ticketCount > 0) {
System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketCount + 1 + "张票"));
ticketCount--;
}
}
}
3,同步函数,所方法,其实是this 锁
证明,两个线程,一个线程走同步代码块,(锁住了自定义object对象)的代码,
另一个走同步函数,锁方法的的代码,结果数据有冲突,证明了syncronized 没有效,并没有锁住同一资源
将锁对象的object 换成this,则没有数据冲突
4,是静态同步函数?
方法上加上static关键字,使用synchronized 关键字修饰 或者使用类.class文件。
静态的同步函数使用的锁是 该函数所属字节码文件对象
还是加syncronized,和之前没有区别,锁方法
public class TrainThread implements Runnable {
// 定义初始化票100张
private static int ticketCount = 100;
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
sale();
}
private synchronized static void sale() {
while (ticketCount > 0) {
System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketCount + 1 + "张票"));
ticketCount--;
}
}
}
锁当前类的的字节码文件的对象,不是this,或者自定义的对象
public class TrainThread implements Runnable {
// 定义初始化票100张
private static int ticketCount = 100;
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (TrainThread.class) {
while (ticketCount > 0) {
System.out.println(Thread.currentThread().getName() + "卖出了第" + (100 - ticketCount + 1 + "张票"));
ticketCount--;
}
}
}
}
线程安全,syncronized 用法的更多相关文章
- 李洪强iOS开发之FMDB线程安全的用法
// // ViewController.m // 04 - FMDB线程安全的用法 // // Created by 李洪强 on 2017/6/6. // Copyright © 2017 ...
- 一个线程中lock用法的经典实例
/* 该实例是一个线程中lock用法的经典实例,使得到的balance不会为负数 同时初始化十个线程,启动十个,但由于加锁,能够启动调用WithDraw方法的可能只能是其中几个 作者:http://h ...
- AtomicInteger类保证线程安全的用法
J2SE 5.0提供了一组atomic class来帮助我们简化同步处理.基本工作原理是使用了同步synchronized的方法实现了对一个long, integer, 对象的增.减.赋值(更新)操作 ...
- java 线程池的用法
1.java自带的类ExecutorService用于提供线程池服务,可以一下方法初始化线程池: ExecutorService pool = Executors.newFixedThreadPool ...
- Java 四种线程池的用法分析
1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { ...
- c#基础: 线程的初级用法总结
启动一个线程的两种方法: a.使用无参的方法 Thread thread1 = new Thread(new ThreadStart("调用的方法名")): ...
- java--ThreadPool线程池简单用法
package com.threadPool; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent. ...
- Android线程之基本用法
一: 在android中有两种实现线程thread的方法: 一种是,扩展java.lang.Thread类 另一种是,实现Runnable接口 二: Thread类代表线程类,它的两个最主要的方法是: ...
- 线程8--GCD常见用法
1.延迟执行 /***********************延迟第一种方法**************************/ /* 第一种方法, 调用NSObject的方法 [self perf ...
随机推荐
- MySQL root密码重置问题
1:进入cmd,停止mysql服务:Net stop mysql (进入服务---->MySql----->停止) 到mysql的安装路径启动mysql,在bin目录下使用mysqld-n ...
- localstorage二次封装-模块模式
var db = function () { // 本地存储前缀,减少命名冲突 var prefix = 'ydb'; return { setPrefix: function (_prefix) { ...
- css 进度条的文字根据进度渐变
需求 1.进度条里面的文字需要根据进度的长度而变化 原理 用两个一模一样的样式的 div 重叠起来 效果 字体开始为 蓝色,跟随进度条变为 白色 在线预览: https://jsfiddle.net/ ...
- JS动画之缓动函数分析及动画库
上一篇讲了JS动画定时器相关知识,这一篇介绍下缓动函数及流行的动画库. 熟悉的图 实际使用 jquery animate()+jquery.easing插件的使用: $(selector).anima ...
- moment太重? 那就试试miment--一个超轻量级的js时间库
介绍 Miment 是一个轻量级的时间库(打包压缩后只有1K),没有太多的方法,Miment的设计理念就是让你以几乎为零的成本快速上手,无需一遍一遍的撸文档 由来 首先 致敬一下Moment,非常好用 ...
- Python学习笔记--迭代
在Python中,迭代是通过for ... in来实现.只要是可迭代的对象都可以用for ... in来进行历遍. 常用的有list.tuple.dict等.举例如下: 列表的迭代: L=[1,2,3 ...
- 一键制作镜像并发布到k8s
*:first-child { margin-top: 0 !important; } .markdown-body>*:last-child { margin-bottom: 0 !impor ...
- Yuchuan_Linux_C编程之六 Makefile项目管理
一.整体大纲 二.makefile的编写 一个规则 两个函数 三个变量 1. 一个规则 三要素:目标, 依赖, 命令 目标:依赖 命令: 第一条规则是用来生成终 ...
- [每日一题系列] LeetCode 1071. 字符串的最大公因子
题目 对于字符串 S 和 T,只有在 S = T + ... + T(T 与自身连接 1 次或多次)时,我们才认定 "T 能除尽 S". 返回最长字符串 X,要求满足 X 能除尽 ...
- Simulink仿真入门到精通(六) Simulink模型保存为图片
6.1 截图保存方式 Ctrl+Alt+A 6.2 拷贝试图方式 Edit→Copy Current View to Clipboard 6.3 saveas函数 用于保存figure或者simuli ...