java基础 关于线程安全
来源:互联网 发布:linux 没有rc.d 编辑:程序博客网 时间:2024/05/16 11:29
A变量安全:多线程同时运行一段代码
B线程同步:一个线程还没执行完,另一个线程又进来接着执行。
看个简单的例子。
- public class ThreadSafeimplements java.lang.Runnable {
- int num = 1;
- public void run() {
- for (int i =0; i < 3; i++) {
- num = num + 1;
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("num is value +==="+Thread.currentThread().getName()+"---------" + num);
- }
- }
- }
public class TestMan {
public static void main(String[] args) {
Runnable safe=new ThreadSafe();
Thread thread1=new Thread(safe,"thread1");
Thread thread2=new Thread(safe,"thread2");
thread1.start();
thread2.start();
}
}
运行结果
num is value +===thread2---------3
num is value +===thread1---------4
num is value +===thread2---------5
num is value +===thread1---------6
num is value +===thread1---------7
num is value +===thread2---------7
很明显是错误的,应为两个线程共享同一个变量。这里就是变量的安全问题。
解决办法:
1抛弃单实例,多线程的方式,用多实例,多线程的方式,这样就和单线程是一个样了,不会出错,但是是最接近传统的编程模式
2不要用类的实例变量,经可能把变量封装到方法内部。
1类的解决办法的代码。
- public class TestMan {
- public staticvoid main(String[] args) {
- Runnable safe=new ThreadSafe();
- Runnable safe2=new ThreadSafe();
- Thread thread1=new Thread(safe,"thread1");
- Thread thread2=new Thread(safe2,"thread2");
- thread1.start();
- thread2.start();
- }
- }
运行结果
num is value +===thread1---------2
num is value +===thread2---------2
num is value +===thread1---------3
num is value +===thread2---------3
num is value +===thread1---------4
num is value +===thread2---------4
2类解决办法的代码
- public class ThreadSafeimplements java.lang.Runnable {
- public void run() {
- int num = 1;
- for (int i =0; i < 3; i++) {
- num = num + 1;
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("num is value +==="+Thread.currentThread().getName()+"---------" + num);
- }
- }
- }
- public class TestMan {
- public staticvoid main(String[] args) {
- Runnable safe=new ThreadSafe();
- Thread thread1=new Thread(safe,"thread1");
- Thread thread2=new Thread(safe,"thread2");
- thread1.start();
- thread2.start();
- }
- }
运行结果
num is value +===thread2---------2
num is value +===thread1---------2
num is value +===thread1---------3
num is value +===thread2---------3
num is value +===thread1---------4
num is value +===thread2---------4
这两种办法,比较推荐适用第二个办法,就是把变量经可能的封装到风发内部,这样他们就是线程的私有变量了。另外,从jdk1.2后,推出了 threadlocal 对象,它作为线程的一个局部变量,可以为每个线程创建一个副本,用来保存每个线程的属性,各是各的,互不干扰。单每个 threadlocal变量只能保存一个变量,假如有多个变量要保存,那么就要写多个threadlocal对象。
我们把代码改写一下。
- public class ThreadSafeimplements java.lang.Runnable {
- ThreadLocal<Integer> local=new ThreadLocal<Integer>();
- public void run() {
- for (int i =0; i < 3; i++) {
- if(local.get()==null){
- local.set(new Integer(1));
- }
- int num=local.get().intValue();
- num=num+1;
- local.set(new Integer(num));
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("num is value +==="+Thread.currentThread().getName()+"---------" + local.get().intValue());
- }
- }
- }
- public class TestMan {
- public staticvoid main(String[] args) {
- Runnable safe=new ThreadSafe();
- Thread thread1=new Thread(safe,"thread1");
- Thread thread2=new Thread(safe,"thread2");
- thread1.start();
- thread2.start();
- }
- }
运行结果
num is value +===thread2---------2
num is value +===thread1---------2
num is value +===thread1---------3
num is value +===thread2---------3
num is value +===thread1---------4
num is value +===thread2---------4
结果是一样的,所以这里变量安全有3个办法可以解决。
然后在说说线程的同步的问题。我们看上面的运行结果。
num is value +===thread2---------2
num is value +===thread1---------2
num is value +===thread1---------3
num is value +===thread2---------3
num is value +===thread1---------4
num is value +===thread2---------4
就 可以看出他们不是线程同步的,是thread1和thread2在交替执行的。在有些情况下,要求一段代码在运行的过程中是一个不可分割的实体,就是原子的。就是说当已经有线程在执行这段代码的时候,其他的线程必须等待他执行完毕后才能竟来执行,这就是所谓的线程同步。
java通过同步锁来执行线程的同步和等待,也就是说,要不间断执行的代码需要放在synchronized关键字标识的代码块中。可以用来修饰代码块,也可以修饰方法。
- public class ThreadSafeimplements java.lang.Runnable{
- public synchronizedvoid run() {
- int num = 1;
- for (int i =0; i < 3; i++) {
- num = num + 1;
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("num is value +==="+Thread.currentThread().getName()+"---------" + num);
- }
- }
- }
- public class TestMan {
- public staticvoid main(String[] args) {
- Runnable safe=new ThreadSafe();
- Thread thread1=new Thread(safe,"thread1");
- Thread thread2=new Thread(safe,"thread2");
- thread1.start();
- thread2.start();
- }
- }
运行结果
um is value +===thread1---------2
num is value +===thread1---------3
num is value +===thread1---------4
num is value +===thread2---------2
num is value +===thread2---------3
num is value +===thread2---------4
可以看到thread1运行结束后thread2才开始运行的。代码还可以这么写
- public class ThreadSafeimplements java.lang.Runnable {
- public void run() {
- int num = 1;
- synchronized (this) {
- for (int i =0; i < 3; i++) {
- num = num + 1;
- try {
- Thread.sleep(2000);
- } catch (InterruptedException e) {
- e.printStackTrace();
- }
- System.out.println("num is value +==="
- + Thread.currentThread().getName() + "---------" + num);
- }
- }
- }
- }
在启用同步锁机制以后,需要避免
1无线等待,,线程B等待线程A执行完毕,然后线程A确进入了死循环。
2循环等待:两个线程相互调用,都要求要同步执行,这个时候就先会循环等待,我等你执行,你也在等我执行,这个时候就死锁了- java 基础,关于线程安全
- java基础 关于线程安全
- JAVA中关于线程安全
- java基础关于线程
- Java基础----线程安全的类
- java并发编程基础之线程安全
- Java并发基础(三)-线程安全
- Java基础之线程安全基本数据类型
- Java多线程基础之线程安全
- java多线程基础篇之线程安全
- Java基础15:线程安全和同步
- java基础—线程安全的定义
- 关于java 线程安全的总结
- java基础关于线程Runnable
- 【Java基础】线程笔记——线程安全
- Java多线程基础——线程和线程安全
- Java多线程基础——线程和线程安全
- java基础—如何创建线程?如何保证线程安全?
- sql oracle分页测试
- ctags使用简介
- 利用System.Net.Mail发送email
- Linux系统--查看Cache
- android 源码结构
- java基础 关于线程安全
- SQLite的升级
- jsp中的动态下拉框的回填方案
- Android学习笔记:Android资源总结
- Linux进程管理与程序开发
- 周五年会之前,市场交投清淡
- C语言学习笔记(一)
- 划分树 POJ 2761 feed the dogs
- poj 1201 Intervals