Thread多线程学习(二),java多线程中synchronize锁的使用和学习

原创 2016年11月15日 11:12:36

synchronize我的理解是为了保证程序中的原子性和一致性,即当你有两个线程同时操作一段代码的时候,要让这段代码的执行是在任何状态下都是正确的,首先要保证synchronize的使用要对同一个对象和同一把锁使用。

public class TraditionalThreadSynchronized {
	
	
	public static void main(String[] args) {
		TraditionalThreadSynchronized test =new TraditionalThreadSynchronized();
		test.init();//创建同一个对象
	}

	private void init(){
		OutPuter outPuter =new OutPuter();
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					while(true){
						Thread.sleep(10);
						outPuter.outer("abcdefg");
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();//线程1
		new Thread(new Runnable() {
			@Override
			public void run() {
				try {
					while(true){
						Thread.sleep(10);
						outPuter.outer("123456789");
					}
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
			}
		}).start();//线程2
	}
	class OutPuter {
		public synchronized void outer(String name) {
				for(int i = 0;i<name.length();i++){
					System.out.print(name.charAt(i));
				}
				System.out.println();
		}
	}
}

我们想要打印的结果是abcdefg和123456789交替打印输出,但是输出结果却是下图


我们发现打印的结果是两个String交替打印出来的,所以这个线程现在是不安全的,那么此时我们就需要使用synchronize保持两个线程的原子性,下面我们把上面程序中的OutPut方法加上synchronize锁试一下

	class OutPuter {
		public void outer(String name) {
				synchronized (name) {
					for(int i = 0;i<name.length();i++){
						System.out.print(name.charAt(i));
					}
					System.out.println();
				}
		}
	}


我们发现加了synchronize关键字的锁以后还是会出现这种线程不安全的情况,那是为什么呢?原因就出在这个锁name上,因为两个线程中的name一个是abcdefg一个是123456789,两个锁根本不是一个锁,所以线程也是不安全的,那么我们再把上面的方法修改一下

class OutPuter {
		public void outer(String name) {
				synchronized (this) {//或者创建一个新的锁把,this换成锁也可以,此处的this指的是outer这个对象
					for(int i = 0;i<name.length();i++){
						System.out.print(name.charAt(i));
					}
					System.out.println();
				}
		}
	}

我们发现此时,上面的程序运行不会出现线程安全问题。

我们此时把上面的syn加在outer上面也是可以的

class OutPuter {
		public synchronized void outer(String name) {
					for(int i = 0;i<name.length();i++){
						System.out.print(name.charAt(i));
					}
					System.out.println();
		}
	}
 这样也是可以实现线程安全的,但是一般情况下synchronize在一段代码中只要使用一次就够了,因为多个synchronize可能会出现死锁问题!

此时我们把上面的OutPuter类修改一下

	class OutPuter {
		public  void outer(String name) {
			synchronized (this) {
				for(int i = 0;i<name.length();i++){
					System.out.print(name.charAt(i));
				}
				System.out.println();
			}
		}
		public synchronized void outer2(String name) {
				for(int i = 0;i<name.length();i++){
					System.out.print(name.charAt(i));
				}
				System.out.println();
		}
	}


然后把上面的outPuter.outer(“123456789”)改成outPuter.outer2(“123456789”)


此时还能保证线程安全么,也就是说output和output2会保持互斥么?当然也是可以的,因为此时的两个锁代表的也是同一把锁,都是代表当前的对象,而当前对象此时是一个对象,所以是可以实现我们想要的效果的。

那么此时我们把上面的

然后把上面的outPuter.outer(“123456789”)改成new outPuter().outer(“123456789”)

我们会发现依然会出现线程安全问题,那是为什么呢 ?那是因为我们每次new的OutPuter()并不是同一个对象。所以说明synchronize既要保证是同一个对象,又要保证是同一把锁。

此时我们再加一个output3方法

	public static synchronized void outer3(String name) {
			for(int i = 0;i<name.length();i++){
				System.out.print(name.charAt(i));
			}
			System.out.println();
	}


注意这个output3方法是静态的,那么我们需要把OutPuter类也改成静态类

然后把上面的outPuter.outer(“123456789”)改成outPuter.outer3(“123456789”)



答案是不行的,因为此时我们使用的output3中的锁是类锁,而output中的锁是当前对象锁,根本不是一把锁,那么此时我们要是想让output和output3同步需要怎么做呢?我们把output中的this改成OutPuter.class就可以实现同步了。此时我们两个方法的锁就都是类锁了,即为同一把锁。

线程还在学习中,学习是痛苦的,但是我希望能真正的坚持做一件事情!


Java线程(初级)——synchronized、死锁、wait、notify详解

线程可以在任意对象的监视器(锁)上阻塞(wait,前提是获取到该对象的锁),也可以在唤醒任意一个wait在某个对象的监视器上的线程(notify,前提是获取到该对象的锁)。“获取到某个对象的锁”,就像...
  • MyTroy
  • MyTroy
  • 2014年08月03日 20:01
  • 2749

Java多线程之深入理解synchronize关键字

synchronize锁重入:关键字synchronize拥有锁重入的功能,也就是在使用synchronize时,当一个线程的得到了一个对象的锁后,再次请求此对象是可以再次得到该对象的锁。 当一个线...
  • qq_32120645
  • qq_32120645
  • 2017年06月07日 16:14
  • 338

深入研究 Java Synchronize 和 Lock 的区别与用法

在分布式开发中,锁是线程控制的重要途径。Java为此也提供了2种锁机制,synchronized和lock。做为Java爱好者,自然少不了对比一下这2种机制,也能从中学到些分布式开发需要注意的地方。 ...
  • natian306
  • natian306
  • 2014年01月19日 15:22
  • 35952

synchronize用法

1、多线程的同步: 1.1、同步机制:在多线程中,可能有多个线程试图访问一个有限的资源,必须预防这种情况的发生。所以引入了同步机制:在线程使用一个资源时为其加锁,这样其他的线程便不能访问那个资源了,...
  • zhangjianjaEE
  • zhangjianjaEE
  • 2017年07月17日 14:34
  • 187

Delphi中多线程中Synchronize的运用

Delphi中多线程用Synchronize实现VCL数据同步显示,Delphi中多线程用Synchronize实现VCL数据同步显示转自:http://blog.csdn.net/maxcode/a...
  • jiangnanandi
  • jiangnanandi
  • 2008年09月22日 17:29
  • 7090

多线程运行同步锁synchronize的一些实战心得

同步锁的应用本质:牺牲程序执行性能而换取数据的安全变动。 原则:如果在实际开发中,在使用同步锁之前,必须先了解你要调用的同步对象,内部是否已经实现了同步,如果实现了同步,则无需加锁,否则就要加锁。 1...
  • u014104512
  • u014104512
  • 2015年03月17日 21:12
  • 1765

Sychronized学习之死锁

package com.ilucky.test.jdk.util.concurrent;/** * 死锁 * 如下这段代码会引起死锁,两个线程会互相等待对方释放锁。 * 一般发生的原因是: 某个...
  • sidongxue2
  • sidongxue2
  • 2017年05月21日 18:20
  • 171

Thread多线程学习(二),java多线程中synchronize锁的使用和学习

synchronize我的理解是为了保证程序中的原子性和一致性,即当你有两个线程同时操作一段代码的时候,要让这段代码的执行是在任何状态下都是正确的,首先要保证synchronize的使用要对同一个对象...
  • a347911
  • a347911
  • 2016年11月15日 11:12
  • 815

java学习视频day01多线程Thread

package cn.itcast.thread; /* 线程: 多线程的好处: 多线程解决了在一个进程中同时可以执行多个任务代码的问题。 自定义线程的创建方式: 方式一:继承Threa...
  • honghong75042
  • honghong75042
  • 2016年10月13日 09:18
  • 372

java多线程和synchronize锁

一、线程的5个状态 1.创建状态 线程对象被创建后,就进入了新建状态。此时它和其他Java对象一样,仅仅由Java虚拟机分配了内存,并初始化其成员变量值。 2.就绪状态  也被称为...
  • qq_36047892
  • qq_36047892
  • 2017年11月19日 21:55
  • 68
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:Thread多线程学习(二),java多线程中synchronize锁的使用和学习
举报原因:
原因补充:

(最多只允许输入30个字)