1.synchronized是Java中的关键字,是一种同步锁。它修饰的对象有以下几种:

1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个代码块的对象;
2. 修饰一个方法,被修饰的方法称为同步方法,其作用的范围是整个方法,作用的对象是调用这个方法的对象;
3. 修改一个静态的方法,其作用的范围是整个静态方法,作用的对象是这个类的所有对象;
4. 修改一个类,其作用的范围是synchronized后面括号括起来的部分,作用主的对象是这个类的所有对象。

2.synchronized的缺陷

synchronized是java中的一个关键字,也就是说是Java语言内置的特性。

如果一个代码块被synchronized修饰了,当一个线程获取了对应的锁,并执行该代码块时,其他线程便只能一直等待,等待获取锁的线程释放锁,而这里获取锁的线程释放锁只会有两种情况:

1)获取锁的线程执行完了该代码块,然后线程释放对锁的占有;

2)线程执行发生异常,此时JVM会让线程自动释放锁。

简单的东西没必要总结,我们来看其中的几个关键点,值得体会,用一个例子说话:

 1 public class Demo4 {
public static void main(String[] args) {
final Output output = new Output();
new Thread(new Runnable() { @Override
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
output.Output1("chenchi");
}
}
}).start(); new Thread(new Runnable() { @Override
public void run() {
while(true){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
output.Output1("sujunjun");
}
}
}).start();
} static class Output {
public void Output1(String name) {
synchronized (this) {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
} public synchronized void Output2(String name) {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
} public synchronized static void Output3(String name) {
for (int i = 0; i < name.length(); i++) {
System.out.print(name.charAt(i));
}
System.out.println();
}
}
}

这个例子很简单,就是同时开启两个线程,声明一个Output内部类的对象,同时访问Output内部类的Output()方法。

1.

output.Output1("chenchi");

output.Output1("sujunjun");

很明显,打印中不会出现数据错误。synchronized ()只要保证括号里面是同一对象就不会产生错误。里面传的是this,由于两者对象都是output,所以加锁成功。

想一下,这样会成功吗?(可以)

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

这样呢?(可以)

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

这样呢?(不可以)

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

2.

output.Output1("chenchi");

output.Output2("sujunjun");

很明显,打印中不会出现错误,因为synchronized修饰方法就是相当于给方法加锁的是当前对象。

3.

output.Output1("chenchi");

output.Output3("sujunjun");

很明显,打印会出错。为什么呢?还是因为加锁对象不是同一个了。synchronized修饰静态方法后,上锁对象为当前类对象了。

什么是当前类对象呢?就是Class类型实例,JVM在加载任何一个类时,都会创建一个Class类型的实例描述该类,并且每个类有且只有一个Class的实例描述它。

如何同步?

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

这里改了一下Output1方法,Output.class为上锁对象,就保证了同一对象。

多线程中的synchronized的更多相关文章

  1. 多线程中的synchronized小结

    1.synchronized是Java中的关键字,是一种同步锁.它修饰的对象有以下几种: 1. 修饰一个代码块,被修饰的代码块称为同步语句块,其作用的范围是大括号{}括起来的代码,作用的对象是调用这个 ...

  2. java多线程中 volatile与synchronized的区别-阿里面试

    volatile 与 synchronized 的比较(阿里面试官问的问题) ①volatile轻量级,只能修饰变量.synchronized重量级,还可修饰方法 ②volatile只能保证数据的可见 ...

  3. [多线程] 线程中的synchronized关键字锁

    为什么要用锁? 在多线程中,难免会出现在多个线程中对同一个对象的实例变量或者全局静态变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实 ...

  4. java中多线程详解-synchronized

    一.介绍 当多个线程涉及到共享数据的时候,就会设计到线程安全的问题.非线程安全其实会在多个线程对同一个对象中的实例变量进行并发访问时发生,产生的后果就是“脏读”.发生脏读,就是取到的数据已经被其他的线 ...

  5. Java多线程4:synchronized锁机制

    脏读 一个常见的概念.在多线程中,难免会出现在多个线程中对同一个对象的实例变量进行并发访问的情况,如果不做正确的同步处理,那么产生的后果就是"脏读",也就是取到的数据其实是被更改过 ...

  6. c#初学-多线程中lock用法的经典实例

    本文转载自:http://www.cnblogs.com/promise-7/articles/2354077.html 一.Lock定义     lock 关键字可以用来确保代码块完成运行,而不会被 ...

  7. 深入理解java中的synchronized关键字

    synchronized 关键字,代表这个方法加锁,相当于不管哪一个线程A每次运行到这个方法时,都要检查有没有其它正在用这个方法的线程B(或者C D等),有的话要等正在使用这个方法的线程B(或者C D ...

  8. Java多线程4:synchronized关键字

    原文:http://www.cnblogs.com/skywang12345/p/3479202.html 1. synchronized原理在java中,每一个对象有且仅有一个同步锁.这也意味着,同 ...

  9. java中的synchronized关键字

    参考:http://www.cnblogs.com/devinzhang/archive/2011/12/14/2287675.html 多线程并发问题的根因: 在一个对象中有一个变量i=0,有两个线 ...

随机推荐

  1. 运维利器-ClusterShell集群管理操作记录

    在运维实战中,如果有若干台数据库服务器,想对这些服务器进行同等动作,比如查看它们当前的即时负载情况,查看它们的主机名,分发文件等等,这个时候该怎么办?一个个登陆服务器去操作,太傻帽了!写个shell去 ...

  2. 史上最全的CSS hack方式一览

    做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我们会极不情愿的使用这个不太友好的方式来达到大家要求的页面表现.我个人是不太推荐使用hack的,要知道 ...

  3. Java集合系列:-----------04fail-fast总结(通过ArrayList来说明fail-fast的原理以及解决办法)

    前面,我们已经学习了ArrayList.接下来,我们以ArrayList为例,对Iterator的fail-fast机制进行了解.内容包括::1 fail-fast简介2 fail-fast示例3 f ...

  4. 由于 ASP.NET 进程标识对全局程序集缓存没有读权限,因此未能执行请求。错误: 0x80131902

    由于 ASP.NET 进程标识对全局程序集缓存没有读权限,因此未能执行请求.错误: 0x80131902 分类: c#2013-06-17 10:22 89人阅读 评论(0) 收藏 举报 ASP.NE ...

  5. httpserver

    改了下 # -*- coding:utf-8 -*- from BaseHTTPServer import HTTPServer, BaseHTTPRequestHandler HOST = &quo ...

  6. Python2.6-原理之类和oop(上)

    来自<python学习手册第四版>第六部分 一.oop:宏伟蓝图(26章) 在这之前的部分中,经常会使用"对象"这个词,其实,到目前为止都是以对象为基础的,在脚本中传递 ...

  7. C#微信开发小白成长教程二(新手接入指南,附视频)

    距离第一讲又已经过去了一个多星期了,本打算一周更新一讲的,奈何实在太忙.最近也在群里发现有一部分人已经可以熟练调用微信的部分接口但却不是很清楚微信公众平台接收消息的一个处理机制.本讲就来介绍下怎么接入 ...

  8. redis性能测试tcp socket and unix domain

    UNIX Domain Socket IPC socket API原本是为网络通讯设计的,但后来在socket的框架上发展出一种IPC机制,就是UNIX Domain Socket.虽然网络socke ...

  9. 学习SQLite之路(四)

    20160621 更新 参考: http://www.runoob.com/sqlite/sqlite-tutorial.html 1. SQLite   alter命令:不通过执行一个完整的转储和数 ...

  10. jQuery api 快速参考[转]

    选择符 匹配 * 所有元素 #id 带有给定ID的元素 element 给定类型的所有元素,比如说html标签 .class 带有给定类的所有元素 a,b 匹配a或者匹配b的元素 a b 作为a后代的 ...