个人理解
锁与线程:
java中锁是相对线程而言的。
线程A使用含有锁S的方法时会持有锁S,完成时释放锁S。
线程A持有锁S时,线程A调用含有锁S的方法,可以通过并调用。
线程A持有锁S时,线程B调用含有锁S的方法,需要先等待线程A释放锁S。
锁的分类:
类锁、对象锁。
每个类含有一个锁,每个对象含有一个锁。
多个对象之间锁不同,对象与类之间锁不同。
锁的属别:
类锁: 静态方法、静态代码块、类.class。
对象锁: 实例方法、实例代码块、类.this等。
死锁:
两线程分别持有锁A、B;然后等待锁B、A释放,互相锁住。
下面的例子打印startA、startB,却因死锁无法打印endA、endB
public static void main(String[] args) {
A a = new A();
B b = new B();
a.run(a,b);
b.run(a,b);
}
static class A{
void run(A a, B b){
new Thread(() -> {
synchronized (a) {
System.out.println("startA");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (b){
System.out.println("endA");
}
}
}).start();
}
}
static class B{
void run(A a, B b){
new Thread(() -> {
synchronized (b) {
System.out.println("startB");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
synchronized (a){
System.out.println("endB");
}
}
}).start();
}
}
为什么说Vector不是完全线程安全的?
Vector对内部操作加锁处理,却无法保证外部多线程操作的安全性。
下面的例子test1和test2分别调用时test1运行到vector.remove(0)时报错,test2因添加了synchronized运行正常。
public static void test1() {
Vector vector = new Vector();
vector.add(111);
new Thread(new Runnable() {
@Override
public void run() {
if(vector.size()>0){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(vector.remove(0));
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
vector.clear();
}
}).start();
}
public static void test2() {
Vector vector = new Vector();
vector.add(111);
new Thread(new Runnable() {
@Override
public void run() {
synchronized (Main.class) {
if (vector.size() > 0) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(vector.remove(0));
}
}
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (Main.class) {
vector.clear();
}
}
}).start();
}