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 用法的更多相关文章

  1. 李洪强iOS开发之FMDB线程安全的用法

    // //  ViewController.m //  04 - FMDB线程安全的用法 // //  Created by 李洪强 on 2017/6/6. //  Copyright © 2017 ...

  2. 一个线程中lock用法的经典实例

    /* 该实例是一个线程中lock用法的经典实例,使得到的balance不会为负数 同时初始化十个线程,启动十个,但由于加锁,能够启动调用WithDraw方法的可能只能是其中几个 作者:http://h ...

  3. AtomicInteger类保证线程安全的用法

    J2SE 5.0提供了一组atomic class来帮助我们简化同步处理.基本工作原理是使用了同步synchronized的方法实现了对一个long, integer, 对象的增.减.赋值(更新)操作 ...

  4. java 线程池的用法

    1.java自带的类ExecutorService用于提供线程池服务,可以一下方法初始化线程池: ExecutorService pool = Executors.newFixedThreadPool ...

  5. Java 四种线程池的用法分析

    1.new Thread的弊端 执行一个异步任务你还只是如下new Thread吗? new Thread(new Runnable() { @Override public void run() { ...

  6. c#基础: 线程的初级用法总结

    启动一个线程的两种方法:     a.使用无参的方法       Thread thread1 = new Thread(new ThreadStart("调用的方法名")):   ...

  7. java--ThreadPool线程池简单用法

    package com.threadPool; import java.util.concurrent.ArrayBlockingQueue; import java.util.concurrent. ...

  8. Android线程之基本用法

    一: 在android中有两种实现线程thread的方法: 一种是,扩展java.lang.Thread类 另一种是,实现Runnable接口 二: Thread类代表线程类,它的两个最主要的方法是: ...

  9. 线程8--GCD常见用法

    1.延迟执行 /***********************延迟第一种方法**************************/ /* 第一种方法, 调用NSObject的方法 [self perf ...

随机推荐

  1. Java基础:浅谈数据输入流/数据输出流《DataInputstream类与DataOutputstream类》

     一.理论概述 数据输入/输出流(DataInputStream类与DataOutputStream类) 允许应用程序以与机器无关的方式从底层输入流中读取基本Java数据类型. 说白了就是,当读取一个 ...

  2. 机器学习基础——详解自然语言处理之tf-idf

    本文始发于个人公众号:TechFlow,原创不易,求个关注 今天的文章和大家聊聊文本分析当中的一个简单但又大名鼎鼎的算法--TF-idf.说起来这个算法是自然语言处理领域的重要算法,但是因为它太有名了 ...

  3. 如何使用@import导入实现了ImportBeanDefinitionRegistrar接口的类?

    如何使用@import导入实现了ImportBeanDefinitionRegistrar接口的类?   在程序开发的时候,我们经常会遇见一个名词“接口”这也是我们做开发人员工作中必不可少的一个技术, ...

  4. 关于css 的垂直居中

    对于元素的水平居中,我根据我自己之前的一些学习来进行一些总结,如果有不对的地方,欢迎指正~ 一.让大小不固定的元素垂直居中 因为:表格的单元格的特别属性:垂直居中等: `div.parent { di ...

  5. htmlhint 规则详解

    HTML 静态检查规则 HTMLHint 工具内置 23 条规则,可以对 HTML 代码文件进行静态代码检查,从而提高 HTML 代码编写的规范和质量.现在把 23 条规则翻译如下. 一.规则列表 标 ...

  6. p2.js 与 createjs 的组合应用

    开始前简单说下其他几款js物理引擎 box2d老牌,功能全面,但是效率低下,移动端基不用考虑的 matterjs  效率目前我测试下来最高,但是依然还在开发中(好像还很缓慢),目前功能局限,而且有bu ...

  7. Codeforces Round #626 (Div. 2, based on Moscow Open Olympiad in Informatics)

    A. Even Subset Sum Problem 题意 给出一串数,找到其中的一些数使得他们的和为偶数 题解 水题,找到一个偶数或者两个奇数就好了 代码 #include<iostream& ...

  8. Sketchup二次开发教程

    Sketchup提供了两套API: C API,主要用于读写SU文件.我们的SU文件导入功能就是用这套API做的 Ruby API,用于开发SU插件 这次我们主要关注Ruby API,因为它是实现更丰 ...

  9. ajax的post提交 序列化json参数

    再一次项目中,很常见的就是我的前端需要异步进行和后端交互 ,然而需要携带一些参数过去,并且参数类型是json 怎么办呢? 这个时候我们就需要 进行参数序列化 很简单就两句话 如下图 我们看 JSON, ...

  10. 16 搭建Spring Data JPA的开发环境

    使用Spring Data JPA,需要整合Spring与Spring Data JPA,并且需要提供JPA的服务提供者hibernate,所以需要导入spring相关坐标,hibernate坐标,数 ...