一、线程同步介绍

  同步:就是协同步调,按照预定的先后顺序执行。比如:你说完我再说。

  线程同步:访问同一个共享资源的时候多个线程能够保证数据的安全性、一致性。

二、JAVA中实现线程同步的方法

  实现进程同步的方法是在共享竞争的资源上加锁,保证对资源的独占性。JAVA中通过关键字synchronized实现同步。看下面的例子

package cn.edu.sdust.AsyTest;

public class TestAsyn implements Runnable {

    Timer timer = new Timer();

    /**
* @param args
*/ public void run(){
timer.add(Thread.currentThread().getName());
} public static void main(String[] args) {
// TODO Auto-generated method stub TestAsyn test1 = new TestAsyn(); Thread t1 = new Thread(test1);
Thread t2 = new Thread(test1);
t1.setName("t1");
t2.setName("t2");
t1.start();
t2.start();
} } class Timer{ int num=0;
public void add(String name){
num++;
try {
Thread.sleep(1); //使当前线程睡眠,切换线程
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(name+"这是线程"+num); }
}

运行结果:

t1这是线程2
t2这是线程2

分析:这是因为当线程t1执行后修改了num=1后睡眠,线程t2执行,修改num=2后睡眠,切换到线程t1执行,此时num已经为2,因此打印t1为第二个线程。显然这种结果不是我们想要的。

如何保证数据的安全性,这里需要对共享资源加锁,实现线程同步。将共享资源add()方法加上关键字synchronized,保证资源的独占性。如下

class Timer{

    int num=0;
public synchronized void add(String name){
num++;
try {
Thread.sleep(1); //使当前线程睡眠,切换线程
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(name+"这是线程"+num); }
}

修改后运行结果:

t1这是线程1
t2这是线程2

解释:通过synchronized对add方法进行加锁,即使通过sleep使线程t1睡眠,线程t1仍然握有该资源的锁,因此t2不能执行,必须等t1执行完释放对资源的锁t2才能执行。(注:sleep与wait区别之一就是sleep后线程仍然握有资源的锁,而wait后线程将会放弃资源的锁,直到被唤醒后重新争夺资源的锁)

三、synchronized的一些特点

  当线程握有synchronized加锁的资源的锁时,其他访问非加锁资源的线程能够执行。如下例子:

public class ThreadAsynchronmous  implements Runnable{

    int n=100;

    public synchronized void   m1(){
System.out.println("m1");
n=1000;
try{
Thread.sleep(5000);
}catch (InterruptedException e){
e.printStackTrace();
}
System.out.println("n="+n);
}
public void m2() throws Exception{ System.out.println("------"+n);
} public void run(){
m1();
}
/**
* @param args
* @throws Exception
*/
public static void main(String[] args) throws Exception {
// TODO Auto-generated method stub
ThreadAsynchronmous t=new ThreadAsynchronmous(); new Thread(t).start();
Thread.sleep(1000); //让线程非主线程先执行,执行m1 /* for(int i=0; i<100; i++){
System.out.println(i);
}*/
t.m2();
    //System.out.println(n);
} }

运行结果:

m1
------1000
n=1000

可以看到在加锁线程执行的同时,主线程仍然可以继续执行,非加锁资源仍然可以被执行。因此,不要在非加锁区对共享变量做修改。以防止数据的不安全、不一致。

JAVA多线程学习2--线程同步的更多相关文章

  1. Java多线程学习总结--线程同步(2)

    线程同步是为了让多个线程在共享数据时,保持数据的一致性.举个例子,有两个人同时取钱,假设用户账户余额是1000,第一个用户取钱800,在第一个用户取钱的同时,第二个用户取钱600.银行规定,用户不允许 ...

  2. java SE学习之线程同步(详细介绍)

           java程序中可以允许存在多个线程,但在处理多线程问题时,必须注意这样一个问题:               当两个或多个线程同时访问同一个变量,并且一些线程需要修改这个变量时,那么这个 ...

  3. java多线程二之线程同步的三种方法

          java多线程的难点是在:处理多个线程同步与并发运行时线程间的通信问题.java在处理线程同步时,常用方法有: 1.synchronized关键字. 2.Lock显示加锁. 3.信号量Se ...

  4. Java多线程编程(4)--线程同步机制

    一.锁 1.锁的概念   线程安全问题的产生是因为多个线程并发访问共享数据造成的,如果能将多个线程对共享数据的并发访问改为串行访问,即一个共享数据同一时刻只能被一个线程访问,就可以避免线程安全问题.锁 ...

  5. Java多线程学习篇——线程的开启

    随着开发项目中业务功能的增加,必然某些功能会涉及到线程以及并发编程的知识点.笔者就在现在的公司接触到了很多软硬件结合和socket通讯的项目了,很多的功能运用到了串口通讯编程,串口通讯编程的安卓端就是 ...

  6. Java多线程与并发——线程同步

    1.多线程共享数据 在多线程的操作中,多个线程有可能同时处理同一个资源,这就是多线程中的共享数据. 2.线程同步 解决数据共享问题,必须使用同步,所谓同步就是指多个线程在同一时间段内只能有一个线程执行 ...

  7. JAVA多线程学习十六 - 同步集合类的应用

    1.引言 在多线程的环境中,如果想要使用容器类,就需要注意所使用的容器类是否是线程安全的.在最早开始,人们一般都在使用同步容器(Vector,HashTable),其基本的原理,就是针对容器的每一个操 ...

  8. JAVA多线程学习十一-线程锁技术

    前面我们讲到了synchronized:那么这节就来将lock的功效. 一.locks相关类 锁相关的类都在包java.util.concurrent.locks下,有以下类和接口: |---Abst ...

  9. Java多线程学习总结--线程概述及创建线程的方式(1)

    在Java开发中,多线程是很常用的,用得好的话,可以提高程序的性能. 首先先来看一下线程和进程的区别: 1,一个应用程序就是一个进程,一个进程中有一个或多个线程.一个进程至少要有一个主线程.线程可以看 ...

随机推荐

  1. Maximum repetition substring 后缀数组

    Maximum repetition substring Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 7578   Acc ...

  2. [Java,MVC] Eclipse下搭建Spring MVC

    转自:http://blog.csdn.net/blue_jjw/article/details/8752466 一.新建Dynamic Web Project 一个web工程最基本的,只看3个地方, ...

  3. Photoshop笔记一

    Photoshop界面认识 Photoshop界面认识 区域划分 工作 (快捷键) 功能键 常用键: 新建图层 剪切并原位粘贴 建立图层组合 合并图层 课程练习讲解 区域划分

  4. onInterceptTouchEvent和onTouchEvent举例分析

    首先自定义三个组件,其关系是:MyLayout在最上面,MySubLayout在MyLayout下面,MyView在MySubLayout下面. 一个点击事件进来,首先是DOWN动作,先是MyLayo ...

  5. C#中的virtual & override

    很奇怪的设计,需要靠着两个Keyword共同作用,才能完成多态——而不是类似Java那样的默认多态.所谓共同作用,即基类使用virtual 标示函数,子类使用override显示重写. 有点奇怪,MS ...

  6. 解决Elementary OS和Windows时间不一致

    解决方案一:把Windows从硬件时间修改成修改成UTC时间,管理员身份运行 Reg add HKLM\SYSTEM\CurrentControlSet\Control\TimeZoneInforma ...

  7. MarkDown认识与入门

    Markdown 是一种轻量级的「标记语言」,它的优点很多,目前也被越来越多的写作爱好者,撰稿者广泛使用.看到这里请不要被「标记」.「语言」所迷惑,Markdown 的语法十分简单.常用的标记符号也不 ...

  8. NodeJS学习之文件操作

    NodeJS -- 文件操作 Buffer(数据块) JS语言自身只有字符串数据类型,没有二进制数据类型,因此NodeJS提供了一个与String对等的全局构造函数Buffer来提供对二进制数据的操作 ...

  9. android sqlite操作(1)

    以下只是我个人的浅见,大神请忽略~ android提供了一个轻量级的数据库sqlite,虽然说是轻量级,但是相对移动设备sqlite绝对够用了. 先说一下sqlite的管理工具吧 sqlite3,使用 ...

  10. 2015英特尔® 实感™ (Intel® RealSense™) 动手开发实验课

    2015年英特尔® 全球实感技术动手实验课路演来到中国, 这次在中国将有北京和广州两站,包括一天的动手实验室活动 - 面向对感知计算.3D 开发和虚拟现实兴趣浓厚的开发人员.英特尔专家将会指导您如何借 ...