在实际应用中,我们通常会遇到多线程安全问题, 涉及到两个因素:

1,多个线程在操作共享数据。

2,有多条语句对共享数据进行运算。

原因:这多条语句,在某一个时刻被一个线程执行时,还没有执行完,就被其他线程执行了。

解决办法:

对多条操作共享数据的语句,只能让一个线程都执行完,在执行过程中,其他线程不可以参与执行。

Java 对于多线程的安全提供了专业的解决方式。线程的同步是保证多线程安全访问竞争资源的一种手段,对于同步,在具体的Java代码中需要完成一下两个操作:

1.把竞争访问的资源标识为private;

2.同步哪些修改变量的代码,使用synchronized关键字同步方法或代码。

格式:

synchronized(对象) {  // 任意对象都可以。这个对象就是锁。

需要被同步的代码;

}

同步的前提:

1、必须要有两个或者两个以上的线程运行;

2、必须是多个线程使用同一个锁;

好处:解决了多线程的安全问题;

弊端:多个线程需要判断锁,较为消耗资源;

注意: 非静态同步函数的对象锁为this,静态同步函数所使用的锁是该方法所在类的字节码文件对象,即类名.class,静态方法里的同步锁都是使用的是类的字节码对象 }

下面这个例子就是使用同步解决安全性问题

public classSynchronizedThread2 {public static voidmain(String[] args) {

User u= new User("wankun", 100); //创建用户对象,设定姓名和账户余额

MyThread t1= new MyThread("线程1", u, 10); //创建自定义线程,

MyThread t2= new MyThread("线程2", u, -50);

MyThread t3= new MyThread("线程3", u, 28);

t1.start();//执行线程,

t2.start();

t3.start();

}

}class MyThread extends Thread { //自定义线程,设置线程的工作

private User wk; //竞争访问的资源定义为私有

private int y = 0; //竞争访问的资源定义为私有

MyThread(String name, User wk,inty) {super(name);this.wk =wk;this.y =y;

}public void run() { //复写run方法,调用use类中的oper方法,更改wk对象的账户余额

wk.oper(y);//oper方法中含有多条语句,所以oper方法需要使用同步方法的形式来解决安全问题

}

}class User { //账户类

private String code; //竞争访问的资源定义为私有

private int cash; //竞争访问的资源定义为私有

User(String code,intcash) {this.code =code;this.cash =cash;

}publicString getCode() {returncode;

}public voidsetCode(String code) {this.code =code;

}public synchronized void oper(int x) { //业务方法,使用了synchronized关键字同步方法,使只有同一时间内只有一个线程可以使用该方法,从而解决多线程安全问题

try{

Thread.sleep(10); //程序休眠10毫秒

this.cash +=x;

System.out.println(Thread.currentThread().getName()+ "运行 ,增加“" + x + "”,当前余额为:" +cash);

Thread.sleep(10);

}catch(InterruptedException e) {

e.printStackTrace();

}

}}

程序运行结果为

用到线程的同步,随之可能会带来死锁问题。

导致死锁的原因:两个线程互相等待竞争资源,导致两边都无法得到资源,而使自己无法运行。

导致死锁的根源在于不适当的运用synchronized来管理线程对特定对象的访问。解决死锁的方法有:

1、撤消陷于死锁的全部进程;

2、逐个撤消陷于死锁的进程,直到死锁不存在;

3、从陷于死锁的进程中逐个强迫放弃所占用的资源,直至死锁消失。

4、从另外一些进程那里强行剥夺足够数量的资源分配给死锁进程,以解除死锁状态

关于sleep方法,wait方法、jion方法

sleep方法与wait方法的区别:

sleep方法是静态方法,wait方法是非静态方法。

sleep方法在时间到后会自己“醒来”,但wait不能,必须由其它线程通过notify(All)方法让它“醒来”。

sleep方法通常用在不需要等待资源情况下的阻塞,像等待线程、数据库连接的。情况一般用wait。

Sleep:线程会释放执行权,但是不释放锁。wait:线程会释放执行权,而且线程会释放锁。

sleep/wait与yeld方法的区别:

调用sleep或wait方法后,线程即进入block状态,而调用yeld方法后,线程进入runnable状态。

wait与join方法的区别:

wait方法体现了线程之间的互斥关系,而join方法体现了线程之间的同步关系。

wait方法必须由其它线程来解锁,而join方法不需要,只要被等待线程执行完毕,当前线程自动变为就绪。

join方法的一个用途就是让子线程在完成业务逻辑执行之前,主线程一直等待直到所有子线程执行完毕。

wait和sleep区别: 分析这两个方法:从执行权和锁上来分析:

wait:可以指定时间也可以不指定时间。不指定时间,只能由对应的notify或者

notifyAll来唤醒。 notifyAll() 方法,起到的是一个通知作用,不释放锁,也不获取锁。只是告诉该对象上等待的线程可以竞争执行了

sleep:必须指定时间,时间到自动从冻结状态转成运行状态(临时阻塞状态)。

wait:线程会释放执行权,而且线程会释放锁。

Sleep:线程会释放执行权,但是不释放锁。

java多线程的安全_java-多线程的安全问题相关推荐

  1. java 锁旗标_Java多线程

    Java多线程 1. 多线程存在的意义 多线程最大的作用就是能够创建"灵活响应"的桌面程序,而编写多线程最大的困难就是不同线程之间共享资源的问题,要使这些资源不会同时被多个线程访问 ...

  2. java线程怎么用_Java多线程基本使用

    一.概念 1.进程 1.1进程:是一个正在进行中的程序,每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元. 1.2线程:就是进程中一个独立的控制单元,线程在控制着进程的执行,一 ...

  3. java线程代码实现_Java 多线程代码实现讲解

    作为一个完全面向对象的语言,Java提供了类 java.lang.Thread 来方便多线程编程,这个类提供了大量的方法来方便我们控制自己的各个线程.那么如何提供给 Java 我们要线程执行的代码呢? ...

  4. java同步与死锁_Java多线程 - 线程同步与死锁

    一.线程同步 1)模拟多个用户同时从银行账户里面取钱 ● Account 类:银行账户类,里面有一些账户的基本信息,以及操作账户信息的方法 //模拟银行账户 classAccount {private ...

  5. java线程知识梳理_Java多线程——多线程相关知识的逻辑关系梳理

    1 学习多线程知识的根本目标 多线程知识的根本目标是:设计稳健的并发程序. 当然,本文无法回答这个实践性很强的问题(这与具体的业务相关,涉及到具体的策略),本文主要阐述相关知识之间的关系,希望初学者不 ...

  6. java中thread实例_Java多线程并发执行demo代码实例

    主类:MultiThread,执行并发类 package java8test; import java.util.ArrayList; import java.util.List; import ja ...

  7. java 多线程压测_java多线程Jmeter压测实现

    笔者最近在看jmeter源码,对多线程处理部分的了解记录如下. Part1 线程与多线程概念 提到线程先来看一下进程(线程的容器)的概念,进程是一个具有独立功能的程序关于某个数据集合的一次运行活动.它 ...

  8. java点名代码滚动_JAVA多线程实现简单的点名系统

    效果图如下: CMain函数: package com.shubing.main; public class CMain { public static void main(String[] args ...

  9. java多线程 生产者消费者_java多线程之-生产者与消费者

    java多线程之-并发协作[生产者与消费者]模型 对于多线程程序来说,不管c/c++ java python 等任何编程语言,生产者与消费者模型都是最为经典的.也就是可以说多线程的并发协作 对于此模型 ...

  10. java 线程面试题_JAVA多线程面试题(一)

    1.进程和线程的区别 一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java运行环境是一个包含了不同的类和程序的单一进 ...

最新文章

  1. HDU1548:A strange lift(Dijkstra或BFS)
  2. Customer Success Case Study Library
  3. excel处置4000行数据卡_【Excel技巧】在Excel中奇偶行提取和奇偶行筛选方法
  4. OpenGL拆分视图
  5. Android 服务入门
  6. 图解TCP 的重传、滑动窗口、流量控制和拥塞控制机制
  7. linux开启多少到多少端口命令,Linux端口命令
  8. STM32工作笔记0020---新建工程模板基于寄存器-M3
  9. Java8-Stream之数值流
  10. matlab 工具函数 —— logdet(A)
  11. 最长公共子序列问题解析
  12. NodeMCU(ESP8266) 接入阿里云物联网平台 踩坑之旅
  13. Minimum Flips to Make a OR b Equal to c(C++ 或运算的最小翻转次数)
  14. 链家重庆二手房爬取以及房价预测
  15. Java ClassLoader类加载机制(二)类加载器
  16. 文档转换 云服务器,文档转换服务
  17. 什么是 DNS? | DNS 的工作方式
  18. [物联网文章之其四] 在物联网中应用机器学习:使用 Android Things 与 TensorFlow
  19. 【MXNet学习16】在MXNet中使用Dropout
  20. 不是程序员还真看不懂的搞笑段子

热门文章

  1. 95-850-020-源码-心跳-JobMaster与TaskExecutor之间的心跳检测
  2. 【MySQL】MySQL 8 新特性
  3. 【Flink】ExceptionInChainedOperatorException: Could not forward element to next operator Buffer
  4. Mac安装telnet
  5. maven:同一个项目内模块之间互相调用
  6. 【spark】spark学习-27-Spark性能调优(2)
  7. 搭建微信公共平台的本地测试
  8. linux apache mod_jk,Linux上安装Apache,安装mod_jk,相关配置
  9. oracle错误01653,oracle 10g 错误 ORA 01653 的解决过程
  10. python字典(dict)合并的操作