源代码编译为字节码加载到虚拟机中。
临界区的概念:
---04- 1-4 -
synchronized:在临界区加锁,sync关联一个monitor对象,线程调用方法进入sync的话就要获得对象锁。多个sync用一把锁,可以锁多个方法的。
---04- 5 --
老的代码:
面向对象优化的:
错误的用法:
sync加在临界区,锁住一个对象或者类保证多线程访问的一致。
---04- 6-9 ---
synchronized加在方法上。
原始的加法:
---04-- 10 ---
线程八锁。
看下笔记。
---04- 11-13 ---
---04- 14 ----
局部变量是线程安全的,但是局部变量的引用不是线程安全的。
代码:
第一个方法,list是成员变量但是他是引用的局部变量所以是不安全的。
第二个是局部变量了:是线程安全的。
--------------------------------------------------------------------------------------------
局部变量暴露给外部会有什么问题?
在ThreadSafe中,线程1调用method1线程2调用method2会有问题吗?
没有问题因为肯定不是线程1的list。
-----
什么情况下会有问题呢?
我不能控制子类的行为:
package cn.itcast.n4;
import java.util.ArrayList;
public class TestThreadSafe {
static final int THREAD_NUMBER = 2;
static final int LOOP_NUMBER = 200;
public static void main(String[] args) {
ThreadSafeSubClass test = new ThreadSafeSubClass();
for (int i = 0; i < THREAD_NUMBER; i++) {
new Thread(() -> {
test.method1(LOOP_NUMBER);
}, "Thread" + (i+1)).start();
}
}
protected void test123(){
System.out.println(888);
}
}
// 线程不安全的
class ThreadUnsafe {
ArrayList<String> list = new ArrayList<>();
public void method1(int loopNumber) {
for (int i = 0; i < loopNumber; i++) {
method2();
method3();
}
}
private void method2() {
list.add("1");
}
private void method3() {
list.remove(0);
}
}
// 改为局部变量
class ThreadSafe {
public final void method1(int loopNumber) {
ArrayList<String> list = new ArrayList<>();
for (int i = 0; i < loopNumber; i++) {
method2(list);
method3(list);
}
}
private void method2(ArrayList<String> list) {
list.add("1");
}
public void method3(ArrayList<String> list) {
System.out.println(1);
list.remove(0);
}
}
class ThreadSafeSubClass extends ThreadSafe{
@Override
public void method3(ArrayList<String> list) {
System.out.println(2);
// 内部有一个新的线程共享资源了
new Thread(() -> {
list.remove(0);
}).start();
}
}
加上method3就会有问题的。
防止子类重写有线程安全问题method1加final或者private:
final:https://www.cnblogs.com/shadow-shine/p/9614072.html
https://blog.csdn.net/qq_36447151/article/details/80405950
---04--- 15-16-17 ---
---04 -18---
String为什么是线程安全的?没有改变共享变量
---04 -19 ---
这个是线程不安全的,用环绕通知解决。
线程安全分析实例。servlet只有一个实例。
不是线程安全的 是 是 不是 不是加final也不是只是引用是不变的
日期是可变类 字符串是不可变类
---
servlet只有一份,service也只有一份。
这个也有线程安全问题。多例的话也是不可以的可能进入前置通知是一个对象进入后置通知是另一个对象。
---04 -20---
Dao没有成员变量整体都是线程安全的。
上面那个userDao也是线程安全的,因为没有共享变量。
userService有成员变量但是是私有的,也是线程安全的。
---再来---
conn不是线程安全的。
---
没有线程安全问题,因为不是单例的。
---
String为什么是final的,如果不是final的那么可知,如果一个类继承了String,然后重写了方法,内部新建了一个线程,那么就是不安全的了。
---04 -21 --
卖票
转账
---04--- 22-25 ---