测试用例(1):使用synchronized方法实现简单售票系统
public class SaleTicket implements Runnable { public int count; public SaleTicket() { count = 30; } public synchronized void startP(){ while (count > 0) { // synchronized (SaleTicket.class) { if (count > 0) { try { Thread.sleep(new Random().nextInt(1000)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "\t当前票号:" + count--); } // } } } public void run() { startP(); } public static void main(String[] args) { SaleTicket st = new SaleTicket(); for (int i = 1; i <= 5; i++) { new Thread(st, "售票点:" + i).start(); } } }
运行结果为:
售票点:1 当前票号:30
售票点:1 当前票号:29
售票点:1 当前票号:28
售票点:1 当前票号:27
售票点:1 当前票号:26
售票点:1 当前票号:25
售票点:1 当前票号:24
售票点:1 当前票号:23
售票点:1 当前票号:22
售票点:1 当前票号:21
售票点:1 当前票号:20
售票点:1 当前票号:19
售票点:1 当前票号:18
售票点:1 当前票号:17
售票点:1 当前票号:16
售票点:1 当前票号:15
售票点:1 当前票号:14
售票点:1 当前票号:13
售票点:1 当前票号:12
售票点:1 当前票号:11
售票点:1 当前票号:10
售票点:1 当前票号:9
售票点:1 当前票号:8
售票点:1 当前票号:7
售票点:1 当前票号:6
售票点:1 当前票号:5
售票点:1 当前票号:4
售票点:1 当前票号:3
售票点:1 当前票号:2
售票点:1 当前票号:1
根据结果我们分析得出结论,synchronized应用到方法上,是得到了该对象(实例)的锁,对象(实例)锁特点是:哪个线程售票点获得该对象(实例)将会独自执行完毕(也就是独自持有"锁"),所以售票点:1先得到了锁,所以一直是它把所有的票都卖完!
Synchronized 方法控制对类成员的访问:每个类实例对应一把锁,每个synchronized方法都必须获得调用该方法的实例的锁方能执行,否则所属线程阻塞,方法一旦 执行,就独占该锁,直到从该方法返回时才将锁释放,此后被阻塞的线程方能获得该锁,重新进入可执行状态。这种机制确保同一时刻对于每一个实例,其所声明为 synchronized的成员函数中至多只有一个处于可执行的状态(因为至多只有一个能够获得该实例对应的锁),从而有效的避免了类成员变量的访问冲突。(多线程并发执行的时候只能有一个线程执行synchronized method(){代码})
测试用例(2):使用synchronized同步块儿实现简单售票系统
public class SaleTicket implements Runnable { public int count; public SaleTicket() { count = 30; } public /*synchronized*/ void startP(){ while (count > 0) { synchronized (SaleTicket.class) { if (count > 0) { try { Thread.sleep(new Random().nextInt(1000)); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName() + "\t当前票号:" + count--); } } } } public void run() { startP(); } public static void main(String[] args) { SaleTicket st = new SaleTicket(); for (int i = 1; i <= 5; i++) { new Thread(st, "售票点:" + i).start(); } } }
运行结果为:
售票点:1 当前票号:30
售票点:1 当前票号:29
售票点:1 当前票号:28
售票点:1 当前票号:27
售票点:1 当前票号:26
售票点:5 当前票号:25
售票点:5 当前票号:24
售票点:5 当前票号:23
售票点:5 当前票号:22
售票点:5 当前票号:21
售票点:5 当前票号:20
售票点:5 当前票号:19
售票点:5 当前票号:18
售票点:5 当前票号:17
售票点:5 当前票号:16
售票点:5 当前票号:15
售票点:5 当前票号:14
售票点:5 当前票号:13
售票点:5 当前票号:12
售票点:5 当前票号:11
售票点:5 当前票号:10
售票点:5 当前票号:9
售票点:5 当前票号:8
售票点:5 当前票号:7
售票点:5 当前票号:6
售票点:5 当前票号:5
售票点:5 当前票号:4
售票点:5 当前票号:3
售票点:5 当前票号:2
售票点:5 当前票号:1
根据结果我们分析得出结论,当两个并发线程访问同一个对象(实例)中的这个synchronized(SaleTicket.class) 当一个线程访问object的一个synchronized(SaleTicket.class)同步代码块时,另一个线程仍然可以访问该object中的非synchronized(this)同步代码块,所以线程“售票点:5”也有机会执行同步块。尤其关键的是,当一个线程访问object的一个synchronized(SaleTicket.class)同步代码块时,其他线程对object中所有其它synchronized(SaleTicket.class)同步代码块的访问将被阻塞,也就是说,当一个线程访问object的一个synchronized(SaleTicket.class)同步代码块时,它就获得了这个object的对象锁。结果,其它线程对该object对象所有同步代码部分的访问都被暂时阻塞。(这种同步块方式缩小了需要安全的地方,同时也加强了程序运行的效率)
相关推荐
多线程注意:wait()方法的调用要有判定条件常用 while () obj.wait(timeout, nanos); ... // Perform action appropriate to condition } synchronized会影响共享数据,但对其他语句的执行不会有规律了!
在Java多线程编程中,线程安全问题通常是指多个线程访问共享资源时可能出现的不一致或错误状态。为了确保并发执行的线程能够正确地处理这些共享资源,Java提供了多种同步机制,其中之一就是同步方法。同步方法通过在...
Java多线程编程中,线程安全问题是常见的挑战,特别是在并发环境下,多个线程可能会同时访问和修改同一份共享资源,导致数据不一致。为了解决这个问题,Java提供了同步机制,其中一种常用的方式就是同步代码块...
Java多线程-线程的安全问题与线程的同步机制介绍 在 Java 多线程编程中,线程安全问题是非常重要的一个话题。当多个线程访问同一个资源时,如果只有读操作那么不会出现线程安全问题,但是如果多个线程对资源进行读...
在Java编程中,多线程是并发编程的重要组成部分,它允许程序同时执行多个任务,从而提高了系统的效率和响应性。然而,在某些场景下,我们可能需要控制线程的执行顺序,确保它们按照特定的顺序交替运行,这在并发编程...
Java 多线程与并发中的 synchronized 关键字是实现同步块的互斥访问和线程的阻塞及唤醒等工作的重要工具。下面将对 synchronized 关键字进行详细分析。 synchronized 关键字的使用场景 synchronized 关键字可以...
本教程将深入讲解Java中的多线程以及同步控制机制,特别是同步代码块和同步方法。 首先,我们要理解什么是线程。线程是程序执行的最小单位,一个进程中可以有多个线程并发执行。在Java中,可以通过实现`Runnable`...
本文从Java多线程的基本概念开始,逐步深入到Java多线程的高级话题,涵盖了Java多线程的所有方面,包括volatile关键字、Java内存模型、Happens-Before关系、synchronized关键字、ConcurrentHashMap、...
在学习Java过程中,自己收集了很多的Java的学习资料,分享给大家,有需要的欢迎下载,希望对大家有用,一起学习,一起进步。
### Java多线程-生产者与消费者问题 #### 一、生产者与消费者问题概览 **1.1 概要** 生产者与消费者问题是计算机科学中一个多线程同步的经典问题。它描述了两个线程如何共享有限资源的场景:一个是生产者...
### Java多线程-避免同步机制带来的死锁问题及用Lock锁解决线程安全问题 #### 死锁 ##### 1. 说明 在多线程编程中,死锁是一种常见的问题,指的是两个或多个线程在执行过程中,因为竞争资源而造成的一种相互等待...
Java多线程同步是指在Java语言中,如何使用synchronized关键字和其他同步机制来确保多线程程序的正确执行。在Java语言中,synchronized关键字用于对方法或者代码块进行同步,但是仅仅使用synchronized关键字还不能...
### Java多线程知识点总结及企业真题解析 #### 一、知识点总结 ##### (1)多线程相关概念 1. **程序、进程和线程的区分**: - **程序**:为了完成特定的任务而编写的指令集合。它是静态的概念。 - **进程**:...
在Java编程中,多线程是并发处理任务的关键技术,特别是在服务器端开发和高并发场景下。本篇文章将深入探讨“最简单的线程安全问题”,并结合相关源码和工具来帮助理解。线程安全问题通常涉及到多个线程对共享资源的...
Java多线程编程中,`synchronized`关键字是实现线程同步的关键,它可以防止多个线程同时访问共享资源,从而避免数据不一致的问题。在Java中,`synchronized`有两种使用方式:同步方法和同步代码块。 1. 同步方法: ...
在Java中,`join()`、`daemon`线程以及同步机制是多线程编程中的重要概念,对于理解和编写高效的并发代码至关重要。 首先,我们来讨论`join()`方法。在多线程环境中,有时候我们需要确保一个线程在执行完它的任务后...
在Java编程语言中,多...同时,理解并掌握这些同步机制的原理和使用场景,对于提升Java多线程编程的能力至关重要。在实际开发中,要特别注意死锁、活锁和饥饿等问题,避免因线程同步不当而导致的性能下降或程序错误。
该示例展示了如何在多线程环境中使用`synchronized`关键字来实现线程间的同步,以避免数据竞争和不一致的问题。通过具体的代码实现,我们将深入理解Java中的线程同步机制,并学习如何在实际编程中正确地使用这些机制...