java多线程-同步和死锁
程序员文章站
2022-03-10 16:03:20
...
多线程:一个进程中开启了不止一个线程,高速CPU时间片的切换调度线程
1、作用:
①可以充分调用系统资源,提高CPU的使用率,执行某些耗时操作;
②可以实现异步调用(主要功能),提高程序的工作效率。
2、问题:
①当线程数量很大时,CPU需要切换调度,会影响性能;
②线程越多,需要的内存空间越大;
③可能会出现线程安全或者死锁等问题。
3、多线程并行和并发的区别:
· 并行:多个处理器或者多核处理器同使执行多个不同的任务;
· 并发:一个处理器处理多个任务。
(多个线程操作共享数据,可能会出现线程安全问题,使用synchronized保证线程同步)
4、线程的同步:以某种方式来确保资源在某一时刻仅被一个线程占用
*同步块和同步方法:
// Synchronized同步方法,当有一个线程访问该方法时,就会拿到同步锁将方法锁住,其他线程再来访问时需要等待上一个线程执行完成
private static /*synchronized*/ void test() {
// 给test方法加synchronized(同步锁),同步方法的同步锁是类的同步锁
System.out.println(Thread.currentThread().getName());
synchronized (ThreadDemo.class) {
// 同步块:当某一线程进入同步块后,
// 其他线程都不能进入,要等待该线程执行完成
for (int i = 0; i < 100; i++) {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
} System.out.println(Thread.currentThread().getName());
}
}
}
5、线程的死锁:如果你已有一个锁并试图获取另一个锁时,就有死锁的危险.
线程1锁住了对象A的监视器,等待对象B的监视器,线程2锁住了对象B的监视器,等待对象A的监视器,就造成了死锁。
**演示死锁,代码如下:创建两个类,相互调用
public class ThreadDemo {
public static void main(String[] args) {
final A a = new A(); //类的实例:A,B默认都是final类型的,因为在内部类中访问
final B b = new B();
//创建2个线程
Thread th1 = new Thread(new Runnable() {
@Override
public void run() {
a.a1(b); //线程1调用A类的a1方法,参数是B类的实例b
}
});
Thread th2 = new Thread(new Runnable() {
@Override
public void run() {
b.b1(a); //线程2调用B类的b1方法,参数是A类的实例a
}
});
th1.setName("线程1");
th2.setName("线程2");
th1.start();
th2.start();
}
}
class A{ //给A类的两个方法都加上锁synchronized,演示死锁状态
public synchronized void a1(B b){ //在A类中接收B类的实例
System.out.println(Thread.currentThread().getName()+"正在调用A类的a1方法!"); //得到当前访问该方法的线程名称
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在A类的a1方法中调用B类的b2方法!");
b.b2();
}
public synchronized void a2(){
System.out.println("A类的a2方法");
}
}
class B{
public synchronized void b1(A a){ //在B类中接收A类的实例
System.out.println(Thread.currentThread().getName()+"正在调用A类的a1方法!");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"正在B类的b1方法中调用A类的a2方法!");
a.a2();
}
public synchronized void b2(){
System.out.println("B类的b2方法");
}
}
上一篇: webpack中常用的loader
下一篇: Java多线程的同步与死锁