Java线程同步是一种确保多个线程在访问共享资源时能够有序执行的技术,避免了数据的不一致性和竞态条件。在给定的示例中,通过两种方式展示了线程同步:synchronized方法和synchronized代码块。
我们来看同步代码块的实现。在`ThreadDemo`类中,售票的例子通过`synchronized`关键字来实现线程同步。`synchronized`关键字作用于一个对象(在这个例子中是字符串`str`),它创建了一个监视器或者称为锁。当一个线程进入同步代码块并执行其中的语句时,该线程会获取到`str`对象的锁,其他尝试进入同步代码块的线程会被阻塞,直到持有锁的线程执行完毕并释放锁。这个过程确保了在任何时候只有一个线程能够执行同步代码块内的售票操作,避免了票数被多个线程同时减去而造成数据不一致的问题。
```java
synchronized(str) {
if(tickets > 0) {
try { Thread.sleep(1); } catch (Exception e) {}
System.out.println(Thread.currentThread().getName() + " is selling ticket --- " + tickets--);
}
}
```
接下来,我们看到同步方法的使用。`sale()`方法被声明为`synchronized`,这意味着任何时刻只有一个线程可以调用此方法。即使在同一个对象上有多个线程,它们也会被串行化地执行`sale()`方法,确保了售票的线程安全。
```java
public synchronized void sale() {
if(tickets > 0) {
try { Thread.sleep(1); } catch (Exception e) {}
System.out.println(Thread.currentThread().getName() + " is selling ticket --- " + tickets--);
}
}
```
同步方法和同步代码块的主要区别在于同步的对象不同。同步方法默认使用当前实例(`this`)作为监视器,而同步代码块可以指定任何对象作为监视器。在示例中,如果四个线程使用不同的监视器(比如每个线程使用不同的字符串对象),那么线程同步将无法实现,因为它们不会竞争同一个锁。
此外,示例还展示了如何根据`str`的值决定使用同步方法还是同步代码块,这进一步说明了可以根据具体需求选择适当的同步机制。
总结一下,Java线程同步通过`synchronized`关键字提供了线程安全的共享资源访问。同步方法和同步代码块是实现同步的两种主要方式,它们都基于监视器(锁)的概念,确保在任何时刻只有一个线程能执行特定的代码段。在多线程编程中,理解并正确使用线程同步是确保程序正确性和避免数据竞争的关键。