标签:现实生活 star 成员 ++ 支持 oca oid fun 保护
因为线程安全问题,举例—银行取钱问题,多线程对同一个银行账户进行取钱任务,账户会出现负值的资产,不符合现实生活
所以,当多个线程访问同一资源时,很容易“偶然”出现安全问题
避免出现安全问题的方法就是同步
第一种是 synchronized代码块
synchronized{
//需要保护的代码
...
}
第二种是 同步方法(用synchronized关键字修饰)
public synchronized void func(){
....
}
ThreadLocal 线程局部变量,支持泛型,通过使用线程局部变量也可以避免多线程访问同一资源时出现“安全问题”,其方式是通过复制多份同一资源的副本供多线程使用,也就是说每一个线程访问时,都拥有一个副本变量
ThreadLocal 只提供三个三个public方法:
T get():返回此线程局部变量中当前线程副本中的值 void remove():删除此线程局部变量中当前线程副本中的值 void set(T value):设置此线程局部变量中当前线程副本中的值
使用如下:
1. class Account{
2. /**
3. * 定义一个ThreadLocal类型的变量,该变量将是一个线程局部变量
4. * 每个线程都会保留该变量的一个副本
5. */
6. private ThreadLocal<String> name = new ThreadLocal<>();
7. //定义一个初始化name成员变量的构造器
8. public Account(String name){
9. this.name.set(name);
10. //下面代码用于访问当前线程的name副本的值
11. System.out.println("-----"+this.name.get());
12. }
13. //name的getter、setter方法
14. public String getName(){
15. return this.name.get();
16. }
17. public void setName(String name){
18. this.name.set(name);
19. }
20. }
21. class MyThread extends Thread{
22. //定义一个Account类型的成员变量
23. private Account account ;
24. public MyThread(Account acct,String name){
25. super(name);
26. this.account = acct;
27. }
28.
29. public void run(){
30.
31. for(int i = 0;i<10;i++){
32. //当i==6时,输出将账户名代替为当前线程名
33. if(i==6){
34. account.setName(getName());
35. }
36. //输出同一个账户的账户名与循环变量
37. System.out.println(account.getName()+"账户i的值:"+i);
38. }
39. }
40. }
41. public class ThreadLocalTest{
42. public static void main(String[] args){
43. //启动两个线程,共享同一个Account
44. Account acct = new Account("初始名");
45. /**
46. * 虽然两个线程共享同一个账户,即只有一个账户名
47. * 但由于账户名是ThreadLocal类,所以每个线程
48. * 都完全拥有各自的账户名副本,因此在i==6之后,将看到
49. * 两个线程访问同一账户时出现不同的账户名
50. */
51. new MyThread(acct,"线程甲").start();
52. new MyThread(acct,"线程乙").start();
53. }
54. }
标签:现实生活 star 成员 ++ 支持 oca oid fun 保护
原文地址:http://www.cnblogs.com/bior/p/7798369.html