我先举个生活上的例子,现在有3个人,有两个男的和一个女的。现在都吃坏肚子了,要去上厕所。这个厕所分为男厕和女厕,但是很不巧,男厕和女厕只有一个蹲坑。面对这种情况,女生有固定的女生厕所,所以女生上厕所不影响男的,但是两个男的就得争蹲坑。所以当一个男的上厕所另一个男的必须等待排队。
这里就引出了线程的同步和异步。这里的男生和女生就是一种异步关系,因为双方没有什么关系。不会有资源上的冲突。但是男的和男的就是一种同步关系。坑位只有一个所以必须有一个先来后到。
所以我对异步的理解:相互线程互不影响。同步的理解:相互线程相互依赖,资源互斥。
在java中如何实现这种同步关系和异步关系?
Java中有一个关键字synchronized中文意思叫阻塞。所以就是当一个线程在运行时候另一个线程得排队等候。所以synchronized就想那个上厕所事件。但是你想男女上厕所不影响把,所以syschronzied,通过一个标记(锁)lock实现。所以这里男生和女生显然是两个厕所门,坑、肯定不是一把锁,男生和男生才是一把锁。
这样的话我们可以通过java代码来实现。
1一个线程类:
package com.fish;
publicclass MyThreadextends Thread {
Object taget;
public MyThread(Object taget) {
super();
this.taget = taget;
}
@Override
publicvoid run() { //在实现thread类的时候我们重写这个方法
synchronized (taget) {//然后在里面阻塞块里面加一个taget,这个就是一把锁。这个锁可是在构造函数里面赋值的哦。
for (int i = 3; i>0; i--) {
System.out.println(Thread.currentThread().getName() +" i=" + i);
}
}
}
}
2.测试类
package com.fish;
publicclass Test {
publicstaticvoid main(String[] args) {
MyThread th1=new MyThread(2); //这个就是男一
MyThread th2=new MyThread(2);//这个就是男二,因为里面有参数2,所以这两个用的是一把锁
MyThread th3=new MyThread(1);
th3.start();//女生上
th1.start();//男1上
th2.start();//男2上
}
}
结果:
Thread-2 i=3
Thread-2 i=2
Thread-0 i=3
Thread-0 i=2
Thread-2 i=1
Thread-0 i=1
Thread-1 i=3
Thread-1 i=2
Thread-1 i=1
我们可以通过结果看出线程th3 和th1执行是没有什么顺序而言的。应该是相互独立且交替的。这就说明了他们是异步的。但是线程th1和th2是有相同构造的参数,说明用同一把锁。
所以th2必须等th1全部执行完才能执行。
生活中同步现象非常常见。比如说老掉牙的买车票问题。其实就是同步的,你想票的总数是固定的,其实买票得排队。不久是一个等待的过程吗?还有人会说多窗口买票呢,那不是相互不影响的吗?其实不是那样的。如果现在有5个窗口,可以排队买票,但是票只剩3张了。你说如果同5个窗口一起买。那么还有2张哪里来?显然应该是这样的。5个人买票,当买票确定的时候,有一个窗口会迅速确定,其他也几乎同时确定。当时第一个人卖完票,系统就会迅速把数据库的库存改变,变为2.接着那个处于页面的等待的人会访问数据库。但是计算机处理数据很快所以你看上去是同时的。而且在数据库中有4个特性,其中就表明数据库是用锁的。为了保证数据的一致性。