说道多线程的安全问题,很多人想到就就是加锁。用到synchronized关键字。

那就要先说说synchronized问什么能够保证线程安全了。

首先要了解线程的工作方式:线程工作分为工作内存和主内存。主内存就是堆和静态区。当线程运行时,首先将主内存的数据拿到工作内存

然后在工作内存中运行,再将数据写回主内存。工作内存是私有的,但是主内存却是共享的。

那么线程不安全的主要根源就是不能线程读写主内存的共享数据。

那么判断要不要加锁,在什么位置加锁就有了依据——共享数据

下面看一个例子:

package code.thread;

public class SynchronizedDome extends Thread{
int a = 0;
Object obj = new Object();
@Override
public void run() {
synchronized(obj) {
for(int i=5;i>0;i--){
System.out.println(a);
a++;
try {
Thread.sleep(0);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} public static void main(String[] args) {
SynchronizedDome dome = new SynchronizedDome();
SynchronizedDome dome2 = new SynchronizedDome();
SynchronizedDome dome3 = new SynchronizedDome();
System.out.println("Thread start:");
dome.start();
dome2.start();
dome3.start();
}
}

执行结果:

Thread start:
0
1
0
0
2
3
1
1
2
3
4
4
2
3
4

看到没,并没有发生错乱,与预想的输出结果一致

那么你可能会说,这是synchronized的功劳。真的是这样的么,稍微改动过一下在看看

package code.thread;

public class SynchronizedDome extends Thread{
int a = 0;
Object obj = new Object();
@Override
public void run() {
//synchronized(obj) {
{
for(int i=5;i>0;i--){
System.out.println(a);
a++;
try {
Thread.sleep(0);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} public static void main(String[] args) {
SynchronizedDome dome = new SynchronizedDome();
SynchronizedDome dome2 = new SynchronizedDome();
SynchronizedDome dome3 = new SynchronizedDome();
System.out.println("Thread start:");
dome.start();
dome2.start();
dome3.start();
}
}

看到没,还是安全的,并没有因为没加锁而发生错乱

那么我没就要分析一下了,根据我们上面所说的,线程的不安全是因为数据的共享

这个例子中,分别new了三个线程对象。

每个对象在栈上有一个变量a,他们分别属于不同的对象。所以三个线程操作的都是属于自己本身类的数据。是对象私有的。

所以不存在数据的共享,那么就不用加锁了。

我没在看一个例子,让他们数据共享,将变量定义为静态变量

package code.thread;

public class SynchronizedDome2 {
public static void main(String[] args) {
Dome dome = new Dome();
Thread thread = new Thread(dome);
Thread thread2 = new Thread(dome); thread.start();
thread2.start(); }
} class Dome implements Runnable {
static int a = 0;
@Override
public void run() {
//synchronized(this){
{
for(int i=0;i<5;i++) {
System.out.println(Thread.currentThread().getName()+": "+a++);
}
}
}
}

输出结果:

Thread-1: 0
Thread-0: 1
Thread-1: 2
Thread-0: 3
Thread-1: 4
Thread-0: 5
Thread-1: 6
Thread-1: 8
Thread-0: 7
Thread-0: 9

这么换乱,而且我们侥幸没有得到错误的结果。如果多运行几次就会看到可能会出现错误的结果

那么下面用锁来解决,看看有什么不同。

程序就是将什么代码加锁注释去掉。

输出结果:

Thread-0: 0
Thread-0: 1
Thread-0: 2
Thread-0: 3
Thread-0: 4
Thread-1: 5
Thread-1: 6
Thread-1: 7
Thread-1: 8
Thread-1: 9

总结:总的来说线程不安全是由于共享数据的读写不同步引起的。当不涉及到共享数据,也就无不安全可说了。

synchronized关键字保证了操作的原子性和可见性。原子性就是说,一个执行步奏完整的执行完毕,不会再执行的过程中被其他线程打断。

可见性是说,当执行完锁定的代码块后,在解锁之前会把最新的数据写入到主内存中。并且清空其他线程工作内存中该数据的值。保证了该数据时最新的。

多线程简单实例(1)真的需要synchronized么?的更多相关文章

  1. Java 多线程 简单实例 (消费者与生成者)的关系

    PS::线程这套东西在PHP里完全是不存在的概念,有待进一步的学习: PS::这个实例是根据书本上的知识进行扩展的,理解程度50%左右吧! 1.定义生产消费环境 package second; pub ...

  2. Java 多线程 简单实例 (Runnable)

    1.多线程实例 package second; public class A implements Runnable { public char stat = '*'; public void run ...

  3. Java 多线程 简单实例 (Thread)

    package second; public class A extends Thread { public void run(){ for(int i = 1;i <= 10 ; i++){ ...

  4. Linux多线程及线程同步简单实例

    一.多线程基本概念 1. 线程的基本概念 ① 线程就是轻量级的进程 ②线程和创建他的进程共享代码段.数据段 ③线程拥有自己的栈 2. 在实际应用中,多个线程往往会访问同一数据或资源,为避免线程之间相互 ...

  5. Win32 API 多线程编程——一个简单实例(含消息参数传递)

    Win32 API进行程序设计具有很多优点:应用程序执行代码小,运行效率高,但是他要求程序员编写的代码较多,且需要管理所有系统提供给程序的资源,要求程序员对Windows系统内核有一定的了解,会占用程 ...

  6. java多线程Lock接口简介使用与synchronized对比 多线程下篇(三)

    前面的介绍中,对于显式锁的概念进行了简单介绍 显式锁的概念,是基于JDK层面的实现,是接口,通过这个接口可以实现同步访问 而不同于synchronized关键字,他是Java的内置特性,是基于JVM的 ...

  7. Java的多线程 简单入门

    Java的多线程 简单入门 首先能够先搞清楚什么是程序.进程.线程,以及它们之间的关系: 定义: 一 程序仅仅是一组指令的有序集合.它是静态的 二 进程是具有一定独立功能的程序关于某个数据集合上的一次 ...

  8. 简单的互斥同步方式——synchronized关键字详解

    目录 1. 关于synchronized关键字 2. synchronized的原理和实现细节 2.1 synchronized可以用在那些地方 2.2 synchronized是如何实现线程互斥访问 ...

  9. (转) C#多线程赛跑实例

    专于:http://blog.csdn.net/lidatgb/article/details/8363035 结合上篇<多线程的基础>,这次我们写一个多线程的赛跑实例,内容很简单:超人和 ...

随机推荐

  1. Kotlin代理属性--官方文档翻译

    代理属性 Delegated Properties 本文为个人翻译的Kotlin官方文档, 原文连接: Delegated Properties 一些特定的常见类型的属性, 尽管我们可以在每次需要的时 ...

  2. 1_NAT模式和桥接模式下的网络配置

    相信当你看到这篇文章时,你一定对linux的桥接模式和NAT模式有所了解,所以你应该是能看懂这篇文件的,希望对你有所帮助,figthing    ! 一.桥接模式:虚拟机和主机是连在同一个路由下的. ...

  3. 环境配置-云服务器jdk与tomcat配置

    我所实践的主机是麻花疼云的主机,第一次试用30天,装了个centos6.5,其实已经用商用专用镜像配置好环境了,包括jdk.tomcat等常用的内容,但是我实在是找不到他们安装在哪个目录下了,我就自己 ...

  4. wpf创建用户控件(计时器控件)

    在vs中新增用户控件 前台xaml如下代码: <UserControl x:Class="Zh.SelfServiceEquipment.UI.ZhControls.CountDown ...

  5. oracle时间范围查询

    当时间精确到秒的指标和时间精确到日的时间进行对比是恒不等于的,但是可以判断大于或者等于的情况. 举个例子,指标[时间精确到秒] select 时间精确到秒 from table where 时间精确到 ...

  6. AHD-模拟高清芯片RN6752替代TVP5150/CJC5150

    RN6752功能:2路CVBS转BT656/601/1302高清视频解码芯片.产品特征输入:2路CVBS(不能同时输入)和S-VIDEO(一般不用)输出:BT601/656/1302支持NTSC,PA ...

  7. 关于mysql的Fetch Time 和 Duration Time

    详见:http://blog.yemou.net/article/query/info/tytfjhfascvhzxcyt411 Stackowerflow 上关于这两个时间有人这样解释 Fetch ...

  8. Linux — 用户组、权限

    Linux 用户组分为:所有者.所在组.其他组 所有者:谁创建,谁是所有者.命令:ls -al 所在组:当创建文件或者文件夹时,这个文件或者文件夹所分配到的用户组,这样就会有效地隔离文件. 其他组:和 ...

  9. unity3d在菜单栏,一键设置Player setting及自动打包并设置apk的存储位置

    项目进行中,领导要求能够进行一键设置Player settings及自动打包并设置apk的位置,所以自己就上网搜索了很多大神的文章.最后是完成了领导需要的功能,在这里记录并分享一下(此项指针对安卓ap ...

  10. 201521123079《java程序设计》第8周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 2. 书面作业 本次作业题集集合 1.List中指定元素的删除(题目4-1) 1.1 实验总结 这题主要是对函 ...