线程安全,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 ...
随机推荐
- Python学习笔记--装饰器的实验
装饰器既然可以增加原来函数的功能,那能不能改变传给原函数的参数呢? 我们实验一下,先上代码: #!/usr/bin/env python # -*- coding: utf-8 -*- # @Date ...
- CVE-2019-0708 远程桌面漏洞复现
漏洞影响Windows版本: Windows XP SP3 x86Windows XP Professional x64 Edition SP2Windows XP Embedded SP3 x86W ...
- HTML常用表单标签
1.表单元素 <form> HTML 表单用于收集用户输入. 代码示例: <form action="http://xxx.xxx.xxx/xxx.php" me ...
- 微信小程序学习简介
如何向微信小程序导入DEMO源码: 参考方法 参考学习小程序官方文档 小程序官方文档 小程序目录简介 app.json :设置一些工程全局的量.js : 写一些函数逻辑.wxml: 调用.js中写的函 ...
- Everything-快速找到你的文件,电脑前的你值得拥有
如果你也是一位电脑使用者,那么你可以考虑下载这个"Everything". Everything是一款非常非常强大的软件.相信不少电脑用户,特别是Windows用户,都尝试使用过W ...
- 把.net Core 项目迁移到VS2019 for MAC
VS2019 for MAC已经发布很长时间了,本以为项目移过去很麻烦,一直没有动作,最近呆家里快发霉了,决定研究研究,没想到一句代码都不需要动,直接完功,这下可以生产了.同学们可以放心整了. 本次平 ...
- js事件委托target
**看一看,瞧一瞧!** 话说要谈事件委托和target.那我们首先来看看什么是事件.话说什么是事件呢?一般的解释是比较重大.对一定的人群会产生一定影响的事情.而在JavaScript中就不是这样了, ...
- php实现post跳转
大家否知道php可以利用header('Location')实现get请求跳转. php利用curl可以实现模拟post请求. 但是却找不到php现成的实现post跳转.那么问题来了,如果有这个需求该 ...
- Linux apache开启虚拟主机伪静态.htaccess
打开apache配置文件 /etc/httpd/conf/httpd.conf 查找“#LoadModule rewrite_module modules/mod_rewrite.so” 去掉前面的# ...
- Linux下git使用
一.安装 本人使用的是centos 7,首先安装git 1.下载git:wget https://Github.com/Git/Git/archive/v2.3.0.tar.gz 2.下载之后解压:t ...