一、线程安全出现的原因
在使用多线程的时候,往往会出现线程安全的问题,我们直到一个共享数据是可以由多个线程一起操作的,但是当一个共享数据在被一个线程操作的过程中,操作未被执行完毕,而此时另一个线程参与进来操作该共享数据,就会导致共享数据存在安全问题
二、解决线程安全问题
如今解决线程安全问题的办法就是当共享数据被一个线程操作完毕后,才能允许其他线程进行操作,所以这里有两个解决线程安全问题的方法,一个是同步代码块,即给操作共享数据的代码加上一个锁(也叫同步监视器),另一个就是同步方法
三、实现线程安全的方法
1、锁(同步监视器)
synchronized (锁){
}
利用synchronized关键字就可以给代码加上锁,该关键字后面的小括号内所放入的就是锁,锁可以是一个任意的类,但是所有线程必须共用一个锁。 下面是锁的使用的例子:
二、同步方法
同步方法与同步代码块不同的地方就是将子线程要允许的代码放到一个方法中,在该方法的名字前面加上synchronized关键字即可,在这里默认的锁为this,所以,通过继承Thread类创建的多线程是不能够使用同步方法的。 具体使用方法如下:
三、死锁问题
在敲代码的时候应该避免死锁。比如:线程1获得锁1然后线程1在获得锁2然后让线程1释放对锁1和锁2的占用,然后线程2去获得
示例代码:
new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock1){
System.out.println(Thread.currentThread().getName()+"拿到了锁1");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"等待锁2");
synchronized(lock2){
System.out.println(Thread.currentThread().getName()+"拿到了锁2");
}
}
}
},"线程1").start();
new Thread(new Runnable() {
@Override
public void run() {
synchronized (lock1){
System.out.println(Thread.currentThread().getName()+"拿到了锁2");
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"等待锁1");
synchronized(lock2){
System.out.println(Thread.currentThread().getName()+"拿到了锁1");
}
}
}
},"线程2").start();
解开锁的运行效果,线程1和线程2逐一运行并释放锁
死锁的运行效果,线程1和线程2同时运行获得锁
死锁产生的原因就是不同的线程都占用着对方需要的同步资源不放弃,都在等待对方释放自己需要的同步资源,从而形成了死锁。