将线程锁加在对象上与锁加在方法上的区别(模拟火车票联网售票系统:多个线程同时出票,保证每张出票的编号连续且不重复。)

  第一种,从结果看来,编号并非随着线程的逐一增加而增加,也意味着不同的人,有的人先抢票,可是线程没有及时运行,抢到票或者买到剩票。

  原因: 虽然方法是加锁了,但是不同的线程运行不确定的,而实际上对这个 票号的生成  并没有加锁限制,导致先买者,抢不到票。----- 票号不重复,但是没有优先概念,不连续。

ticketNum: 5 Thread Name: Thread 1  线程1 先启动并调用生成票方法, 之后得到5号票
ticketNum: 8 Thread Name: Thread 8
ticketNum: 7 Thread Name: Thread 7
ticketNum: 1 Thread Name: Thread 3
ticketNum: 10 Thread Name: Thread 10
ticketNum: 0 Thread Name: Thread 0
ticketNum: 4 Thread Name: Thread 2
ticketNum: 6 Thread Name: Thread 6
ticketNum: 2 Thread Name: Thread 5 
package test;

public class Starter {

	public static void main(String[] args) {
		for(int i=0;i<50;i++){
			BookTicketThread book=new BookTicketThread("Thread "+i);
		}
	}

}

package test;

public class BookTicketThread extends Thread{

	private String name;
	private Data data;

	public BookTicketThread(String name){
		this.name=name;
		//this.data=data;
		start();
	}

	@Override
	public void run() {
			System.out.println("ticketNum: "+Data.getTicketNum()+" Thread Name: "+name);   // Data.getTicketNum 方法被锁住,这时候调用该方法的可能是任意一个线程,所有线程都有相同的竞争权利。所以1号线程 可能被迫得到五号票。
	}

}

package test;

public class Data{

	private static int ticketNum;

	public synchronized static int getTicketNum(){
		return ticketNum++;
	}

}

result:
ticketNum: 5 Thread Name: Thread 1
ticketNum: 8 Thread Name: Thread 8
ticketNum: 7 Thread Name: Thread 7
ticketNum: 1 Thread Name: Thread 3
ticketNum: 10 Thread Name: Thread 10
ticketNum: 0 Thread Name: Thread 0
ticketNum: 4 Thread Name: Thread 2
ticketNum: 6 Thread Name: Thread 6
ticketNum: 2 Thread Name: Thread 5
ticketNum: 13 Thread Name: Thread 13
ticketNum: 3 Thread Name: Thread 4
ticketNum: 14 Thread Name: Thread 14
ticketNum: 12 Thread Name: Thread 12
ticketNum: 11 Thread Name: Thread 11
ticketNum: 16 Thread Name: Thread 16
ticketNum: 9 Thread Name: Thread 9
ticketNum: 17 Thread Name: Thread 17
ticketNum: 18 Thread Name: Thread 18
ticketNum: 15 Thread Name: Thread 15
ticketNum: 19 Thread Name: Thread 19
ticketNum: 20 Thread Name: Thread 20
ticketNum: 21 Thread Name: Thread 21
ticketNum: 22 Thread Name: Thread 22
ticketNum: 23 Thread Name: Thread 23
ticketNum: 24 Thread Name: Thread 24
ticketNum: 25 Thread Name: Thread 25
ticketNum: 26 Thread Name: Thread 26
ticketNum: 27 Thread Name: Thread 27
ticketNum: 28 Thread Name: Thread 28
ticketNum: 29 Thread Name: Thread 29
ticketNum: 30 Thread Name: Thread 30
ticketNum: 31 Thread Name: Thread 31
ticketNum: 32 Thread Name: Thread 32
ticketNum: 33 Thread Name: Thread 33
ticketNum: 34 Thread Name: Thread 34
ticketNum: 35 Thread Name: Thread 35
ticketNum: 36 Thread Name: Thread 36
ticketNum: 37 Thread Name: Thread 37
ticketNum: 38 Thread Name: Thread 38
ticketNum: 39 Thread Name: Thread 39
ticketNum: 40 Thread Name: Thread 40
ticketNum: 41 Thread Name: Thread 41
ticketNum: 42 Thread Name: Thread 42
ticketNum: 43 Thread Name: Thread 43
ticketNum: 44 Thread Name: Thread 44
ticketNum: 45 Thread Name: Thread 45
ticketNum: 46 Thread Name: Thread 46
ticketNum: 47 Thread Name: Thread 47
ticketNum: 48 Thread Name: Thread 48
ticketNum: 49 Thread Name: Thread 49

  

方法二: 锁住对象,正所谓要得到优先权,锁住方法不能保持得到结果的先后顺序,需要将整个对象锁定,来得到结果才可以保证结果的有序。

package test;

public class Starter {

	public static void main(String[] args) {
		Data data=new Data();
		for(int i=0;i<50;i++){
			BookTicketThread book=new BookTicketThread("Thread "+i,data);
		}
	}

}

package test;

public class BookTicketThread extends Thread{

	private String name;
	private Data data;

	public BookTicketThread(String name,Data data){
		this.name=name;
		this.data=data;
		start();
	}

	@Override
	public void run() {
			System.out.println("ticketNum: "+data.getTicketNum()+" Thread Name: "+name);
	}

}

package test;

public class Data{

	private  int ticketNum;

	public synchronized  int getTicketNum(){
		return ticketNum++;
	}

}

  result: 连续 且不重复。

ticketNum: 0 Thread Name: Thread 0
ticketNum: 4 Thread Name: Thread 4
ticketNum: 3 Thread Name: Thread 3
ticketNum: 2 Thread Name: Thread 2
ticketNum: 6 Thread Name: Thread 6
ticketNum: 1 Thread Name: Thread 1
ticketNum: 7 Thread Name: Thread 7
ticketNum: 5 Thread Name: Thread 5
ticketNum: 8 Thread Name: Thread 8
ticketNum: 9 Thread Name: Thread 9
ticketNum: 10 Thread Name: Thread 10
ticketNum: 11 Thread Name: Thread 11
ticketNum: 12 Thread Name: Thread 12
ticketNum: 13 Thread Name: Thread 13
ticketNum: 14 Thread Name: Thread 14
ticketNum: 15 Thread Name: Thread 15
ticketNum: 16 Thread Name: Thread 16
ticketNum: 17 Thread Name: Thread 17
ticketNum: 18 Thread Name: Thread 18
ticketNum: 19 Thread Name: Thread 19
ticketNum: 20 Thread Name: Thread 20
ticketNum: 21 Thread Name: Thread 21
ticketNum: 22 Thread Name: Thread 22
ticketNum: 23 Thread Name: Thread 23
ticketNum: 24 Thread Name: Thread 24
ticketNum: 25 Thread Name: Thread 25
ticketNum: 26 Thread Name: Thread 26
ticketNum: 27 Thread Name: Thread 27
ticketNum: 28 Thread Name: Thread 28
ticketNum: 29 Thread Name: Thread 29
ticketNum: 30 Thread Name: Thread 30
ticketNum: 31 Thread Name: Thread 31
ticketNum: 32 Thread Name: Thread 32
ticketNum: 33 Thread Name: Thread 33
ticketNum: 34 Thread Name: Thread 34
ticketNum: 35 Thread Name: Thread 35
ticketNum: 36 Thread Name: Thread 36
ticketNum: 37 Thread Name: Thread 37
ticketNum: 38 Thread Name: Thread 38
ticketNum: 39 Thread Name: Thread 39
ticketNum: 40 Thread Name: Thread 40
ticketNum: 41 Thread Name: Thread 41
ticketNum: 42 Thread Name: Thread 42
ticketNum: 43 Thread Name: Thread 43
ticketNum: 44 Thread Name: Thread 44
ticketNum: 45 Thread Name: Thread 45
ticketNum: 46 Thread Name: Thread 46
ticketNum: 47 Thread Name: Thread 47
ticketNum: 48 Thread Name: Thread 49
ticketNum: 49 Thread Name: Thread 48
时间: 2024-08-01 20:35:38

将线程锁加在对象上与锁加在方法上的区别(模拟火车票联网售票系统:多个线程同时出票,保证每张出票的编号连续且不重复。)的相关文章

[原创]java WEB学习笔记79:Hibernate学习之路--- 四种对象的状态,session核心方法:save()方法,persist()方法,get() 和 load() 方法,update()方法,saveOrUpdate() 方法,merge() 方法,delete() 方法,evict(),hibernate 调用存储过程,hibernate 与 触发器协同工作

本博客的目的:①总结自己的学习过程,相当于学习笔记 ②将自己的经验分享给大家,相互学习,互相交流,不可商用 内容难免出现问题,欢迎指正,交流,探讨,可以留言,也可以通过以下方式联系. 本人互联网技术爱好者,互联网技术发烧友 微博:伊直都在0221 QQ:951226918 -----------------------------------------------------------------------------------------------------------------

springmvc 在方法上使用 @ModelAttribute 注解

在方法上使用 @ModelAttribute 注解 @ModelAttribute注解不仅可以用在方法上也可以用在方法参数上.本节讲述@ModelAttribute在方法上的使用,下一节将讲述其在方法参数上的使用. 在方法上使用 @ModelAttribute 注解的目的是添加一个或者多个model属性中.这些方法支持@RequestMapping方法对应的参数,但是不能直接和请求映射. 在同一个Controller中@ModelAttribute 注解的方法将先于@RequestMapping

ModelMap对象的 addAttribute,put两个方法区别

这个是 源码中 ModelMap的定义 类 public class ModelMap extends LinkedHashMap<String, Object> 说明 ModelMap是继承自LinkedHashMap的,则put方法是继承自 HashMap的方法,没什么特殊而addAttribute方法的定义public ModelMap addAttribute(String attributeName, Object attributeValue) { Assert.notNull(a

JAVA之旅(十四)——静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制

JAVA之旅(十四)--静态同步函数的锁是class对象,多线程的单例设计模式,死锁,线程中的通讯以及通讯所带来的安全隐患,等待唤醒机制 JAVA之旅,一路有你,加油! 一.静态同步函数的锁是class对象 我们在上节验证了同步函数的锁是this,但是对于静态同步函数,你又知道多少呢? 我们做一个这样的小实验,我们给show方法加上static关键字去修饰 private static synchronized void show() { if (tick > 0) { try { Thread

Java同步—线程锁和条件对象

线程锁和条件对象 在大多数多线程应用中,都是两个及以上线程需要共享对同一数据的存取,所以有可能出现两个线程同时访问同一个资源的情况,这种情况叫做:竞争条件. 在Java中为了解决并发的数据访问问题,一般使用锁这个概念来解决. 有几种机制防止代码收到并发访问的干扰: 1.synchronized关键字(自动创建一个锁及相关的条件) 2.ReentrantLock类+Java.util.concurrent包中的lock接口(在Java5.0的时候引入) ReentrantLock的使用 publi

有关多线程(同步锁,递归锁,同步对象,信号量)

上面一个随笔已经简单介绍了多线程,比如下面在举个简单的例子: 1 #!/usr/bin/env python 2 #-*-coding:utf-8 -*- 3 4 import threading 5 import time 6 7 def add(): 8 sum = 0 9 10 for i in range(1000000): 11 sum += i 12 13 print("sum: ",sum) 14 15 16 def mul(): 17 sum2 = 1 18 for i

python学习第37天GIL锁、死锁现象与递归锁、信号量、Event时间、线程queue

一.GIL锁 1. 什么是GIL全局解释器锁 定义: In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython's memory management is not thread-safe

Python学习第47天(递归锁、同步对象、信号量)

今天三个部分的知识.递归锁(解决同步锁造成的锁死现象).同步对象(类似一个锁,使两个线程之间进行同步).信号量(控制线程数量的一个锁),悄悄的说一下,算上昨天的同步锁,虽然已经讲了四种锁了,但是据说总共是有五种锁的,最后一个我还不知道是个啥. 一.递归锁 昨天引入了同步锁的概念,但是因为同步锁的引入,又发生了一个问题,就是两个锁来回锁,导致程序最终被锁死,你等我我等你,谁都没法运行了,先看一下锁死的情况吧,情况如下: import threading,time class myThread(th

【转】多线程:C#线程同步lock,Monitor,Mutex,同步事件和等待句柄(上)

本篇从Monitor,Mutex,ManualResetEvent,AutoResetEvent,WaitHandler的类关系图开始,希望通过 本篇的介绍能对常见的线程同步方法有一个整体的认识,而对每种方式的使用细节,适用场合不会过多解释.让我们来看看这几个类的关系图: 1.lock关键字      lock是C#关键词,它将语句块标记为临界区,确保当一个线程位于代码的临界区时,另一个线程不进入临界区.如果其他线程试图进入锁定的代码,则它将一直等待(即被阻止),直到该对象被释放.方法是获取给定