线程安全问题 &synchronized 知识点总结 包含代码分析

package com.day02;

/**
* @author anyan
* @date 2021/5/9-8:20
*/
/*
关于线程安全问题的总结
1.何时发生线程安全问题(条件)
(1)存在多线程并发
n个线程n个栈,不同栈抢占CPU时间片并发执行
(2)多线程存在资源共享
例如:多个线程 共享同一个变量/常量/对象
变量分类:a.成员变量:实例变量,静态变量。 b.局部变量
*实例变量存在堆内存中,静态变量存在方法区中。局部变量存放在栈内存中。常量存放在常量池中,不可变。
*堆内存和方法区只有一块,因此成员变量存在共享。
而栈内存有无数块,与线程数量保持一致,因此局部变量为每个线程所特有,不存在共享。
(3)共享资源发生改变
*由于常量不可变,因此不存在线程安全问题
2.synchronized是一个关键字,标识需要执行线程同步的部分 格式: synchronized(唯一对象){需要同步的代码;}
3.线程同步范围越广,CPU执行效率越低,反之则越高
*例如:若对字符串常量(实例变量)进行线程同步操作。对线程中某一个方法进行线程同步操作.二者对比,明显后者效率高
*由于字符串常量在堆内存中,是每个线程共有的。因此但凡线程开始执行,必定要同步,但有些时候并线程只需在某些位置同步
例如使用某个方法的时候
4.synchronized的用法
a.加在同步方法上,普通方法锁对象:this 静态方法锁对象:类的字节码文件对象
b. synchronized(唯一对象){需要同步的代码;} 此方法较灵活
*/
public class SynchronizedTest01 {
public static void main(String[] args) {
Account act = new Account("10010011", 2000);
Account act1=new Account("11001111",2000);
Account act2=new Account("1002221",2000);
//at1,at2,at3线程同步
AccountThread at1 = new AccountThread(act);
AccountThread at2=new AccountThread(act);
AccountThread at3=new AccountThread(act);
//三个同步线程与at4,at5线程并发
AccountThread at4=new AccountThread(act1);
AccountThread at5=new AccountThread(act2);
at1.setName("张三");
at2.setName("李四");
at3.setName("王五");
/* at4.setName("赵四");
at5.setName("王二麻子");*/
at1.start();
at2.start();
at3.start();
/* at4.start();
at5.start();*/
}
}
//账户类
class Account{
private String name;//账户名
private double balance;//账户余额

public Account() {
}
public Account(String name, double balance) {
this.name = name;
this.balance = balance;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public double getBalance() {
return balance;
}

public void setBalance(double balance) {
this.balance = balance;
}
//账户取款方法
public s synchronized void withDraw(double money) throws InterruptedException {
double first=this.balance;//取款前余额
double after=first-money;//取款后余额
Thread.sleep(1000*2);
this.setBalance(after);//刷新账户余额
}
}
//账户线程(进行取钱操作)
class AccountThread extends Thread {
//提供成员变量,以实现线程共享账户资源
Account account;
//多线程共享一个账户对象
public AccountThread(Account account) {
this.account = account;
}
//指向run方法时,线程对象开始取款
@Override
public void run() {
try {
//同步当前对象调用成员变量中的某个方法
// synchronized (this.account) {
this.account.withDraw(100);
// }
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"取款成功 余额:"+this.account.getBalance());
}
}
posted @ 2021-05-09 10:25  安妍  阅读(94)  评论(0)    收藏  举报