下面是Java中线程状态、线程安全问题以及synchronized的用法详解,包含示例说明:
Java中线程状态
Java中的线程状态主要有以下五种:
- 新建状态(New):线程对象被创建后,但还没有调用start()方法时,线程处于新建状态。
- 运行状态(Runnable):当线程对象调用start()方法后,线程就处于运行状态。在运行状态下,线程会不断地执行run()方法。
- 阻塞状态(Blocking):线程进入阻塞状态时,表示线程暂时不能执行。常见的情况有:等待输入输出、调用sleep()方法、调用wait()方法等。
- 等待状态(Waiting):线程进入等待状态时,表示线程一直等待某个条件的满足,直到其他线程调用notify()或notifyAll()方法来唤醒线程。
- 终止状态(Terminated):线程进入终止状态时,表示线程执行完毕或者出现异常终止。
线程安全问题
在多线程环境下,如果多个线程同时对共享数据进行读写操作,就会引发线程安全问题。常见的线程安全问题有:资源竞争、死锁等。为了避免线程安全问题,我们通常采用以下几种方法:
- 加锁(synchronized):对共享数据进行加锁,保证同一时刻只有一个线程可以访问共享数据。
- 利用CAS操作(Atomic类):利用CPU提供的CAS指令实现线程安全的操作。
- 使用线程安全的类库(如ConcurrentHashMap等):Java中提供了一些线程安全的类库,可以直接使用。
synchronized的用法详解
synchronized是Java中用于实现加锁的关键字,可以修饰代码块和方法。当一个线程进入一个synchronized代码块或方法时,它就会尝试获取对象的锁,如果获取锁成功,就可以执行相应的代码。如果获取锁失败,则该线程会进入阻塞状态,直到其他线程释放该对象的锁。
下面是synchronized的用法示例:
public class SynchronizedDemo {
private int count = 0;
public synchronized void addCount() {
count++;
}
public int getCount() {
return count;
}
public static void main(String[] args) throws InterruptedException {
SynchronizedDemo demo = new SynchronizedDemo();
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
demo.addCount();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
demo.addCount();
}
});
t1.start();
t2.start();
// 等待两个线程执行完毕
t1.join();
t2.join();
System.out.println("Count: " + demo.getCount());
}
}
在上面的示例中,我们定义了一个SynchronizedDemo类,其中包含了一个count变量和两个线程t1和t2。这两个线程通过调用addCount()方法来对count变量进行累加操作。
由于addCount()方法是synchronized方法,当一个线程进入该方法时,它就会获取该对象的锁。而由于t1和t2对应的是同一个对象,因此它们同一时刻只能有一个线程执行addCount()方法。这样就避免了线程安全问题,保证了累加操作的正确性。
除了修饰方法之外,synchronized还可以修饰代码块,示例代码如下:
public class SynchronizedDemo2 {
private static int count = 0;
public static void addCount() {
synchronized (SynchronizedDemo2.class) {
count++;
}
}
public static int getCount() {
return count;
}
public static void main(String[] args) throws InterruptedException {
Thread t1 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
SynchronizedDemo2.addCount();
}
});
Thread t2 = new Thread(() -> {
for (int i = 0; i < 10000; i++) {
SynchronizedDemo2.addCount();
}
});
t1.start();
t2.start();
// 等待两个线程执行完毕
t1.join();
t2.join();
System.out.println("Count: " + SynchronizedDemo2.getCount());
}
}
在上面的示例中,我们定义了一个SynchronizedDemo2类,其中包含了一个静态的count变量和两个线程t1和t2。在addCount()方法中,我们使用了synchronized关键字修饰了代码块,锁对象为SynchronizedDemo2类本身。这样的话,所有对SynchronizedDemo2类的static成员变量的访问都会被限制为同步的。
注:为了保证线程的执行顺序与预期一致,示例代码中使用了join()方法等待线程执行完毕。
本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java中线程状态+线程安全问题+synchronized的用法详解 - Python技术站