当多线程同时对一个全局变量进行写的操作的时候。可能会受到其他线程的干扰,就会发生线程安全性问题。在多个线程对一个变量做竞争的时候就会大概率的发生线程安全问题。
public class ThreadCount implements Runnable{
private static int count = 100;
@Override
public void run() {
//死循环是为了保证线程一直在运行状态
while (true){
if (count > 1){
count --;
System.out.println(Thread.currentThread().getName() + "," + count);
}
}
}
public static void main(String[] args) {
ThreadCount threadCount = new ThreadCount();
new Thread(threadCount).start();
new Thread(threadCount).start();
}
}
如何解决线程安全问题?/多线程如何实现同步?
这两个属于同一个问题,都是在问如何解决线程安全问题。解决问题的核心思想是:上锁!当多个线程共享同一个全局变量的时候,将可能会发生线程安全的代码上锁,保证只有拿到锁的线程才可以执行该代码;没有拿到锁的线程不可以执行,需要阻塞等待。
在同一个jvm中,多个线程需要竞争锁的资源,最终只能够有一个线程,能够获取到锁,多个线程同时抢同一把锁,谁(线程)能够获取到锁,谁就可以执行到该代码,如果没有获取锁成功 中间需要经历锁的升级过程,如果一致没有获取到锁则会一直阻塞等待。如果线程A获取锁成功 但是线程A一直不释放锁,线程B一直获取不到锁,则会一直阻塞等待。
注意:不是将全部代码上锁,而是将可能发生线程安全的代码加锁!
锁:重入锁、悲观锁、乐观锁、公平锁、非公平锁
比如synchronized锁就是非公平锁,看运气,谁抢到就是谁用。线程0和线程1同时获取this锁,假设线程0获取到了this,意味着线程1没有获取到就会阻塞等待。等线程0执行完释放锁之后,重新竞争锁。
synchronized锁的获取锁与释锁都是自动的,全部都是由底层虚拟机实现好的。
public class ThreadCount implements Runnable{
private static int count = 100;
@Override
public void run() {
while (true){
if (count > 1){
synchronized(this){
count --;
System.out.println(Thread.currentThread().getName() + "," + count);
}
}
}
}
public static void main(String[] args) {
ThreadCount threadCount = new ThreadCount();
new Thread(threadCount).start();
new Thread(threadCount).start();
}
}
加上锁后的缺点:可能会影响到程序的执行效率,加上锁后就会成为单线程。