4.多线程之同步

一、同步:synchronized

同步 并发 多个线程访问同一资源,确保资源安全---->线程安全

  • 同步块:

Synchronized(引用类型 | this | 类.class){

}

  • 同步方法: public static synchronized void....   ---->Web12306

web12306代码实现:

package com.cust.syn;
/**
 *
 * 描述:同步 并发 多个线程访问同一资源
 * synchronized 线程安全
 * @author cookie
 */
public class SynDemo01 {
	public static void main(String[] args) {
		//真实角色
		Web12306 w = new Web12306();
		//三个代理角色
		Thread t1 = new Thread(w,"路人甲");
		Thread t2 = new Thread(w,"黄牛乙");
		Thread t3 = new Thread(w,"攻城狮");
		t1.start();
		t2.start();
		t3.start();
	}
}
class Web12306 implements Runnable {
	private boolean flag = true;
    int num = 10;
	@Override
	public void run() {
		while(flag){
			test5();
		}
	}

	//锁定资源不正确 --->线程不安全 速率比较高
	public void test5() {
		// a b c
		synchronized ((Integer) num) { // 锁定
			if (num <= 0) {
				flag = false;// 线程结束
				return;
			}
			// a b c
			try {
				Thread.sleep(500);// Runnable无法往外抛出异常
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName() + "抢到了第张"+ num-- + "票");
		}
	}// a b = 0 c = -1

	//锁定范围不正确 --->线程不安全 速率比较高
	public void test4(){
		// a b c
		synchronized(this){  // 锁定 调用此方法的对象 即 Web12306
			if(num <=0){
				flag = false;//线程结束
				return;
			}
		}
		// a b c
		try {
			Thread.sleep(500);//Runnable无法往外抛出异常
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"抢到了第张"+ num-- +"票");
	}//a   b = 0  c = -1

	//锁定同步块 --->线程安全 速率较低
	public void test3(){
		synchronized(this){  // 锁定 调用此方法的对象 即 Web12306
			if(num <=0){
				flag = false;//线程结束
				return;
			}
			try {
				Thread.sleep(500);//Runnable无法往外抛出异常
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			System.out.println(Thread.currentThread().getName()+"抢到了第张"+ num-- +"票");
		}
	}
	//锁定方法 --->线程安全 速率较低
	public synchronized void test2(){
		if(num <=0){
			flag = false;//线程结束
			return;
		}
		try {
			Thread.sleep(500);//Runnable无法往外抛出异常
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"抢到了第张"+ num-- +"票");

	}
	//并发 不处理 ---->线程不安全   速率较低
	public void test1(){
		if(num <=0){
			flag = false;//线程结束
			return;
		}
		try {
			Thread.sleep(500);//Runnable无法往外抛出异常
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		System.out.println(Thread.currentThread().getName()+"抢到了第张"+ num-- +"票");

	}
}

 二、单例模式 

  懒汉式 和 饿汉式

package com.cust.syn;

/**
 * 单例模式
 *   gc  JVM   垃圾桶  Runtime
 * 懒汉式:  double checking 双重检查
 *   1.构造器私有化
 *   2.声明一个私有的静态变量
 *   3.创建一个共有的静态方法,访问变量,并确保有变量
 *  饿汉式:
 *
 * @author cookie
 */
public class SingletonDemo {

}
/**
 *   懒汉式:  double checking 双重检查
 *   1.构造器私有化
 *   2.声明一个私有的静态变量
 *   3.创建一个共有的静态方法,访问变量,并确保有变量
 * @author cookie
 */
class JVM{
	private static JVM jvm;
	private JVM(){
	}
	public static JVM getInstance(){
		if(null == jvm){ //提高效率,在对象已经存在的情况下不进入该方法
			synchronized(JVM.class){  //静态方法中不能调用this
				if(null==jvm){  //如果不存在,则创建对象 安全
					jvm = new JVM();
				}
			}
		}
		return jvm;
	}
}
/**
 * 饿汉式:
 *   1.构造器私有化
 *   2.声明一个私有的静态变量,并同时实例化该变量
 *   3.创建一个共有的静态方法,访问变量
 * @author cookie
 */
class JVM2{
	private static JVM2 jvm = new JVM2();
	private JVM2(){
	}
	public static JVM2 getInstance(){ //不使用这个方法,变量可能被初始化
		return jvm;
	}
}
/**
 * 类在使用时加载,延缓加载时间(MyJvm)  饿汉式推荐
 * @author cookie
 */
class JVM3{
	private static class MyJvm{
		private static JVM3 jvm = new JVM3();
	}
	private JVM3(){
	}
	public static JVM3 getInstance(){//不使用这个方法,不会加载MyJvm
		return MyJvm.jvm;
	}
}

  三、死锁:过多的同步容易造成死锁

/**
 *
 * 描述:死锁:过多的同步容易造成死锁
 * @author cookie
 */
public class SynDemo03 {
	public static void main(String[] args) {
		Object g = new Object();
		Object m = new Object();
		Test t1 = new Test(g,m);
		Test2 t2 = new Test2(g,m);
		Thread proxy = new Thread(t1);
		Thread proxy2 = new Thread(t2);
		proxy.start();
		proxy2.start();
	}
}
class Test implements Runnable{
	Object goods;
	Object money;
	public Test(Object goods, Object money) {
		this.goods = goods;
		this.money = money;
	}

	@Override
	public void run() {
		test();
	}
	public void test(){
		synchronized(goods){
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			synchronized(money){

			}
		}
		System.out.println("一手给钱");
	}
}
class Test2 implements Runnable{
	Object goods;
	Object money;
	public Test2(Object goods, Object money) {
		this.goods = goods;
		this.money = money;
	}
	@Override
	public void run() {
		test();
	}
	public void test(){
		synchronized(money){
			try {
				Thread.sleep(200);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
			synchronized(goods){

			}
		}
		System.out.println("一手给货");
	}
}

  四、解决死锁:生产者消费者 信号量法

package com.cust.pro;

/**
 * 一个场景 共同的资源 生产者消费者模式 信号灯法 Object: wait() 释放锁 等待 sleep()不释放锁
 * notify()/notifyAll() 唤醒等待
 *
 * @author cookie
 */
class Movie {
	private String pic;
	// 信号灯
	// 信号灯法
	// flag---->T 生产者生产,消费者等待,生产完生产毕后,唤醒消费者
	// flag---->F 消费者消费,生产者等待,消费者消费完毕后,唤醒生产者
	private boolean flag = true;

	public synchronized void play(String pic) {
		if (!flag) {// 消费者消费 生产者等待
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		try {
			Thread.sleep(100);
		} catch (InterruptedException e1) {
			e1.printStackTrace();
		}
		// 生产结束
		this.pic = pic;
		System.out.println("生产了:" + pic);
		// 唤醒消费者,
		this.notifyAll();
		// 生产者结束
		this.flag = false;

	}

	public synchronized void watch() {
		if (flag) {// 生产者生产,消费者等待
			try {
				this.wait();
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
		// 消费者消费
		try {
			Thread.sleep(200);
		} catch (InterruptedException e) {
			e.printStackTrace();
		}
		// 消费完毕
		System.out.println("消费了:" + this.pic);
		// 唤醒生产者
		this.notify();
		// 消费者等待
		this.flag = true;

	}
}
 class Player implements Runnable{
	private Movie m;
	public Player(Movie m) {
		this.m = m;
	}
	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			if(0==i%2){
				m.play("左青龙");
			}else{
				m.play("右白虎");
			}
		}
	}

}
 class Watcher implements Runnable{
	private Movie m;

	public Watcher(Movie m) {
		this.m = m;
	}

	@Override
	public void run() {
		for (int i = 0; i < 20; i++) {
			m.watch();
		}
	}

}
public class App {
	public static void main(String[] args) {
		//共同的资源
		Movie m = new Movie();
		//多线程
		Player p = new Player(m);
		Watcher w = new Watcher(m);

		new Thread(p).start();
		new Thread(w).start();
	}
}

  

时间: 2024-08-06 03:43:28

4.多线程之同步的相关文章

简单的多线程并发同步演示

#include "stdafx.h"#include <iostream>#include <Windows.h>using namespace std;HANDLE hMutex;DWORD WINAPI Fun(LPVOID lp){    while(1){        WaitForSingleObject(hMutex,INFINITE);        cout<<"fun"<<endl;//如果不用信

多线程之同步与死锁

面试的时候被问到,在线性回归中,有三个假设,是哪三个? 当时回答出来自变量x和因变量y之间是线性变化关系,也就是说,如果x进行线性变化的话,y也会有相应的线性变化. 提到数据样本的时候也答道了样本点之间要求是独立同分布的(根据MLE准则,假定对样本加上高斯白噪声e的情况下). 但是第三个最终还是没有答上来,面试官也没有再给提示,所以回来自己再查一下. LR的wiki页面(http://en.wikipedia.org/wiki/Linear_regression)中,有提到了LR的假设,分别是:

多线程以及同步问题

1.在单例设计模式中,会出现多线程的同步问题.主要表现在,当使用的是懒汉式单例设计模式来创建对象的时候,若有多个进程同时在执行,则有可能会创建了多个对象,但这个不是单例设计模式应该出现的问题.所以需要使用锁机制来解决.需要注意的是,饿汉式不会出现这个问题.具体代码如下. 1 class Singleton_lazy{ 2 //懒汉式 3 private Singleton_lazy(){} 4 5 private static Singleton_lazy INSTANCE = null; 6

Python标准库08 多线程与同步 (threading包)

Python主要通过标准库中的threading包来实现多线程.在当今网络时代,每个服务器都会接收到大量的请求.服务器可以利用多线程的方式来处理这些请求,以提高对网络端口的读写效率.Python是一种网络服务器的后台工作语言 (比如豆瓣网),所以多线程也就很自然被Python语言支持. (关于多线程的原理和C实现方法,请参考我之前写的Linux多线程与同步,要了解race condition, mutex和condition variable的概念) 多线程售票以及同步 我们使用Python来实

Java 多线程(五) 多线程的同步

Java 多线程(五) 多线程的同步 为什么要引入同步机制 在多线程环境中,可能会有两个甚至更多的线程试图同时访问一个有限的资源.必须对这种潜在资源冲突进行预防. 解决方法:在线程使用一个资源时为其加锁即可. 访问资源的第一个线程为其加上锁以后,其他线程便不能再使用那个资源,除非被解锁. 程序实例 用一个取钱的程序例子,来说明为什么需要引入同步. 在使用同步机制前,整体程序如下: public class FetchMoneyTest { public static void main(Stri

转载自~浮云比翼:Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥)

Step by Step:Linux C多线程编程入门(基本API及多线程的同步与互斥) 介绍:什么是线程,线程的优点是什么 线程在Unix系统下,通常被称为轻量级的进程,线程虽然不是进程,但却可以看作是Unix进程的表亲,同一进程中的多条线程将共享该进程中的全部系统资源,如虚拟地址空间,文件描述符和信号处理等等.但同一进程中的多个线程有各自的调用栈(call stack),自己的寄存器环境(register context),自己的线程本地存储(thread-local storage). 一

浅谈Java多线程的同步问题 【转】

多线程的同步依靠的是对象锁机制,synchronized关键字的背后就是利用了封锁来实现对共享资源的互斥访问. 下面以一个简单的实例来进行对比分析.实例要完成的工作非常简单,就是创建10个线程,每个线程都打印从0到99这100个数字,我们希望线程之间不会出现交叉乱序打印,而是顺序地打印. 先来看第一段代码,这里我们在run()方法中加入了synchronized关键字,希望能对run方法进行互斥访问,但结果并不如我们希望那样,这是因为这里synchronized锁住的是this对象,即当前运行线

浅谈Java多线程的同步问题

多线程的同步依靠的是对象锁机制,synchronized关键字的背后就是利用了封锁来实现对共享资源的互斥访问. 下面以一个简单的实例来进行对比分析.实例要完成的工作非常简单,就是创建10个线程,每个线程都打印从0到99这100个数字,我们希望线程之间不会出现交叉乱序打印,而是顺序地打印. 先来看第一段代码,这里我们在run()方法中加入了synchronized关键字,希望能对run方法进行互斥访问,但结果并不如我们希望那样,这是因为这里synchronized锁住的是this对象,即当前运行线

Linux多线程与同步

Linux多线程与同步 作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 典型的UNIX系统都支持一个进程创建多个线程(thread).在Linux进程基础中提到,Linux以进程为单位组织操作,Linux中的线程也都基于进程.尽管实现方式有异于其它的UNIX系统,但Linux的多线程在逻辑和使用上与真正的多线程并没有差别. 多线程 我们先来看一下什么是多线程.在Linux从程序到进程中,我们看到了一个程序在内存中的表示.这个程

【转】【玩转cocos2d-x之二十三】多线程和同步03-图片异步加载

原创作品,转载请标明:http://blog.csdn.net/jackystudio/article/details/15334159 cocos2d-x中和Android,Windows都 一样,如果在主线程中处理一些耗时操作,那么主线程就会出现阻塞现象,表现在界面上就是卡住,未响应等情况.为了避免这种情况的出现,我们需要在后台开辟 工作线程进行数据的处理,再采用消息传递或者其他形式来通知主线程进行UI变化.最常见的情况就是游戏进入前的loading. 1.图片的异步加载 在多线程和同步的第