java线程研究---(8)Thread同步:锁的概念

(多线程数据共用的)示例代码:

先来看看“java线程研究---(7)Thread同步:多线程数据共用会产生问题”这篇文章里面主要的代码例子

ShareDataThread.java

package thread;

public class ShareDataThread implements Runnable {

	private int i = 0;

	@Override
	public void run() {
		while (i < 10) {
			i++;
			for (int j = 0; j < 10000000l; j++)
				;
			System.out.println(Thread.currentThread().getName() + ": " + i);
		}
	}
}

OneObjExample.java

package thread;

public class OneObjExample {

	public static void main(String abc[]) {

		ShareDataThread s1 = new ShareDataThread();

		Thread t1 = new Thread(s1);
		Thread t2 = new Thread(s1);

		t1.start();
		t2.start();
	}
}

运行结果(其实每次运行结果都不一样的,如下结果只不过是典型的一次结果):

Thread-1: 1

Thread-1: 3

Thread-0: 4

Thread-1: 5

Thread-0: 6

Thread-1: 7

Thread-1: 8

Thread-0: 9

Thread-1: 10

Thread-0: 10

分析运行结果:

我就如上的结果,有如下的分析(或者说猜测,因为多线程这东西,这能根绝现象去揣测,无从得到底这两个线程是如何交替运行的):

  1. 为什么2没有打印出来?

    • thread-1打印1完毕之后,
    • thread-1继续执行i++
    • thread-1接着执行for循环,由于执行for循环需要较长的时间,
    • thread-1还没有来得及打印2,thread-1就被cpu替换下来了。。。
    • thread-0开始执行,此时thread-0所拿到的i=2,
    • thread-0,在执行i++之后,i=3
    • thread-0接着执行for循环,由于执行for循环需要较长的时间,
    • thread-0还没有来得及打印3,thread-0就被cpu替换下来了。。。
    • thread-1开始执行,此时thread-1所拿到的i=3,
    • 注意,此时thread-1是继续上一次他被cpu替换下来的点继续执行,所以
    • thread-1直接开始打印3!
    • 大家多读读几遍,看看我分析的对不?
  2. 为什么打印两个10?
    • 其实也很好分析
    • Thread-1,在要打印之前,被cpu替换下来
    • Thread-1再被cpu调用,开始执行的时候,所拿到的i=10。由于是继续上一次代码行号执行,所以
    • Thread-1执行打印10。
    • Thread-1继续while循环,但是条件不成立,while循环结束,Thread-1进入死亡状态。
    • Thread-0,也是在要打印之前,被cpu替换下来
    • Thread-0再被cpu调用,开始执行的时候,所拿到的i依旧是10。由于是继续上一次代码行号执行,所以
    • Thread-0执行打印10。
    • Thread-0继续while循环,但是条件不成立,while循环结束,Thread-0也进入死亡状态。
    • 小妹分析的太深入了,有木有

结论总结:

针对于这个示例代码,和打印的结果,综合分析,我的总结就是:

  • i++
  • for循环
  • 打印
  • 这三行代码,只要被其他线程进来,分割,侵入,就会造成数据打印不一致的结果。
  • 因此,得让这三行代码,具有原子性!不可分割,无法被其他线程进来侵入,打断这三行代码连续执行
  • 所以给这三行代码加锁,那么这三行代码就变成了一个整体,具有原子性!
  • 好啦,锁的概念,由此诞生!

锁:synchronized

之前的文字,都是为了现在,引入锁的概念,为什么有锁,加锁的目的等。

话不多说,直接看上锁之后的代码

ShareDataThread.java加锁后的修改如下。

package thread;

public class ShareDataThread implements Runnable {

	private int i = 0;

	@Override
	public void run() {
		while (i < 10) {
			synchronized(this){   // 锁块
				i++;
				for (int j = 0; j < 10000000l; j++);
				System.out.println(Thread.currentThread().getName() + ": " + i);
			}
		}
	}
}

OneObjExample.java 执行类,不变

package thread;

public class OneObjExample {

	public static void main(String abc[]) {

		ShareDataThread s1 = new ShareDataThread();

		Thread t1 = new Thread(s1);
		Thread t2 = new Thread(s1);

		t1.start();
		t2.start();
	}
}

运行结果如下:

Thread-1: 1

Thread-1: 2

Thread-1: 3

Thread-0: 4

Thread-0: 5

Thread-1: 6

Thread-1: 7

Thread-0: 8

Thread-0: 9

Thread-0: 10

Thread-1: 11

注意:运行结果,似乎不怎么尽如人意,稍后我会继续完善的。

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-10-20 09:48:12

java线程研究---(8)Thread同步:锁的概念的相关文章

Java线程与并发编程实践----锁框架

Java.util.concurrent.locks包提供了一个包含多种接口和类的框架,它 针对条件进行加锁和等待.不同于对象的内置加锁同步以及java.lang.Object的等 待/通知机制,包含锁框架的并发工具类通过轮询锁.显示等待及其它方式改善这种 机制. 锁框架包含了经常使用的锁.重入锁.条件.读写锁以及冲入读写锁等类别. 一.锁(Lock) Lock 实现提供了比使用 synchronized 方法和语句可获得的更广泛的锁定操作.此实 现允许更灵活的结构,可以具有差别很大的属性,可以

Java线程状态及Thread类中的主要方法

要想实现多线程,就必须在主线程中创建新的线程对象. 任何线程一般具有5种状态,即创建,就绪,运行,阻塞,终止. 创建状态: 在程序中用构造方法创建了一个线程对象后,新的线程对象便处于新建状态,此时,他已经有了相应的内存空间和其他资源,但还处于不可运行状态. 就绪状态: 新建线程对象后,调用该线程的start()方法可以启动线程.当线程启动时,线程进入就绪状态.此时,线程将进入线程队列排队,等待CPU服务,这表明它已经具备了运行条件.-------(运行start()方法只是进入就绪状态,并没有开

Java线程示例 - 继承Thread类和实现Runnable接口

进程(Process)和线程(Thread)是程序运行的两个基本单元.Java并发编程更多的是和线程相关. 进程 进程是一个独立的执行单元,可将其视为一个程序或应用.然而,一个程序内部同事还包含多个进程.Java运行时环境就是一个单独的进程,在它内部还包含了作为进程的各种类和程序. 线程 可以将线程看做轻量级的进程.线程存在于进程当中,需要的资源开销较小.同一进程中的线程共享进程的资源. Java多线程 每一个Java引用都只要有一个线程 - 主线程(main thread).虽然后台还运行着许

【Java】多线程冲突解决——同步锁

转载请注明原文地址:http://www.cnblogs.com/ygj0930/p/5827547.html 解决并行冲突最有效的方法就是加同步锁,主要有以下几种方法: 1:动态方法同步锁:锁当前对象.即调用该方法的类对象优先执行完毕才到下一个任务. public synchronized void 方法() { } 实例代码: import java.lang.Thread.State; import org.omg.CORBA.PUBLIC_MEMBER; public class Thr

Java线程状态(Thread.State)

java.lang.Thread.State 成员内部类 NEW:还未启动 Thread state for a thread which has not yet started. RUNNABLE:正在jvm中运行,但是可能正在等待操作系统的其他资源 Thread state for a runnable thread. A thread in the runnable state is executing in the Java virtual machine but it may be w

java 线程之对象的同步和异步

一.多线程环境下的同步与异步 同步:A线程要请求某个资源,但是此资源正在被B线程使用中,因为同步机制存在,A线程请求不到,怎么办,A线程只能等待下去. package com.jalja.org.thread.demo01; public class Thread02 { public synchronized void method1(){ System.out.println("method1:"+Thread.currentThread().getName()); try { T

java线程学习-Thread.currentTread().getName()和this.getName()的区别

很久没有写java程序了,由于为了改变目前的状况,打算花两天时间学习一下java的线程开发和高并发. 线程开发使用thread类,或者runnable接口,而且thread类也是实现了runnable接口的. 先来个小甜点作为开始,如下为创建多个线程,并且同时处理. package firstThreadStudy; public class MyThread extends Thread { public MyThread(){ System.out.println("MyThread cur

Java线程并发中常见的锁--自旋锁 偏向锁

随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想是,如果程序没有竞争,则取消之前已经取得锁的线程同步操作.也就是说,若某一锁被线程获取后,便进入偏向模式,当线程再次请求这个锁时,就无需再进行相关的同步操作了,从而节约了操作时间,如果在此之间有其他的线程进行了锁请求,则锁退出偏向模式.在JVM中使用-XX:+UseBiasedLocking pac

Java线程并发中常见的锁

随着互联网的蓬勃发展,越来越多的互联网企业面临着用户量膨胀而带来的并发安全问题.本文着重介绍了在java并发中常见的几种锁机制. 1.偏向锁 偏向锁是JDK1.6提出来的一种锁优化的机制.其核心的思想是,如果程序没有竞争,则取消之前已经取得锁的线程同步操作.也就是说,若某一锁被线程获取后,便进入偏向模式,当线程再次请求这个锁时,就无需再进行相关的同步操作了,从而节约了操作时间,如果在此之间有其他的线程进行了锁请求,则锁退出偏向模式.在JVM中使用-XX:+UseBiasedLocking pac