一、synchronized

  同步关键字,分为同步代码块和同步函数

二、对synchronized的理解(未加static关键字)(以下所说:对同步方法和同步代码块均适用)

  对象的创建是以类为模板的

  1、两个并发的线程访问同一个类Object中的synchronized(this)同步代码块或者同步方法时,同一时间只能执行一个,另一个必须要等待当前线程执行完才能执行(同一个对象:见下面的testSynchronized,分为两个线程,两个线程访问的是一个方法)(一个对象两个线程一个方法)

     例子:

 public class TestSynchronized {
public void test1(){
synchronized(this) {
System.out.println("1"+this);
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
final TestSynchronized testSynchronized = new TestSynchronized();
final TestSynchronized testSynchronized1 = new TestSynchronized();
Thread thread1 = new Thread(new Runnable() { @Override
public void run() {
testSynchronized.test1();
}
},"test1");
Thread thread3 = new Thread(new Runnable() { @Override
public void run() {
testSynchronized.test1();
}
},"test3"); thread1.start();
thread3.start();
}
}

结果:

  2、两个并发的线程访问同一个类Object中的synchronized(this)同步代码块或者同步方法时,两个交替进行,因为对象的创建是以类为模板的,所以两个对象都会有自己独立的方法(不同对象:testSynchronized和testSynchronized1,分为两个线程,两个线程访问的是一个方法)(两个对象两个线程一个方法)

   例子:和第一个的例子相比仅仅修改了第31行

 public class TestSynchronized {
public void test1(){
synchronized(this) {
System.out.println("1"+this);
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static void main(String[] args) {
final TestSynchronized testSynchronized = new TestSynchronized();
final TestSynchronized testSynchronized1 = new TestSynchronized();
Thread thread1 = new Thread(new Runnable() { @Override
public void run() {
testSynchronized.test1();
}
},"test1");
Thread thread3 = new Thread(new Runnable() { @Override
public void run() {
testSynchronized1.test1();
}
},"test3");
thread1.start();
thread3.start();
}
}

  结果:

  

  3、(两个线程同一对象)当一个线程已经访问了该类中的一个synchronized方法,另一个线程就不能再去访问访问其他的synchronized方法(对象锁是锁住了对象,所以只能执行完这个再去执行另一个)(一个对象两个线程两个方法)

  例子:

 public class TestSynchronized {
public void test1(){
synchronized(this) {
System.out.println("1"+this);
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public synchronized void test2(){
System.out.println(this);
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
final TestSynchronized testSynchronized = new TestSynchronized();
final TestSynchronized testSynchronized1 = new TestSynchronized();
Thread thread1 = new Thread(new Runnable() { @Override
public void run() {
testSynchronized.test1();
}
},"test1");
Thread thread2 = new Thread(new Runnable() { @Override
public void run() {
testSynchronized.test2();
}
},"test2");
thread1.start();
thread2.start();
}
}

  结果:

  

  4、(同一个对象)当一个线程已经访问了一个类的synchronized方法,那么另一个线程也可以访问其他的非synchronized方法,结果是交替进行的(一个对象两个线程两个方法[一个synchronized一个非synchronized的])

    进行了同步的方法(加锁方法)和没有进行同步的方法(普通方法)是互不影响的,一个线程进入了同步方法,得到了对象锁,其他线程还是可以访问那些没有同步的方法(普通方法)

    例子:

 public class TestSynchronized {
public void test1(){
synchronized(this) {
System.out.println("1"+this);
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
//非synchronized
public void test2(){
System.out.println(this);
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
final TestSynchronized testSynchronized = new TestSynchronized();
final TestSynchronized testSynchronized1 = new TestSynchronized();
Thread thread1 = new Thread(new Runnable() { @Override
public void run() {
testSynchronized.test1();
}
},"test1");
Thread thread2 = new Thread(new Runnable() { @Override
public void run() {
testSynchronized.test2();
}
},"test2"); thread2.start();
thread1.start();
}
}

  结果:

  

三、加了static后现成的执行

  1、对于一个类,一个线程访问了加了static的synchronized方法,另一个线程同样可以访问未加static的synchronized方法,所以结果是交替进行,因为类和对象不同(static修饰后锁住的是类,所有对象共享,而没有加static锁住的是对象,只有每个对象私有)(一个对象一个类两个线程两个方法)

  例子:

 public class TestSynchronized {
public void test1(){
synchronized(this) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static synchronized void test2(){
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
final TestSynchronized testSynchronized = new TestSynchronized();
Thread thread1 = new Thread(new Runnable() { @Override
public void run() {
            //对象调用的是该对象自己的方法
testSynchronized.test1();
}
},"test1");
Thread thread2 = new Thread(new Runnable() { @Override
public void run() {
           //类调用的是类方法
TestSynchronized.test2();
}
},"test2");
thread2.start();
thread1.start();
}
}

  结果:

  

  2、两个都是被static修饰的synchronized方法,结果是一个线程等待另一个线程执行完才会执行,因为类是一样的(和同一个对象的理解差不多),方法被synchronized修饰只能一个执行完再执行另一个(一个类两个线程两个方法)

  例子:

 public class TestSynchronized {
public static void test1(){
synchronized(TestSynchronized.class) {
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
public static synchronized void test2(){
int i = 5;
while( i-- > 0) {
System.out.println(Thread.currentThread().getName() + " : " + i);
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static void main(String[] args) {
final TestSynchronized testSynchronized = new TestSynchronized();
Thread thread1 = new Thread(new Runnable() { @Override
public void run() {
TestSynchronized.test1();
}
},"test1");
Thread thread2 = new Thread(new Runnable() { @Override
public void run() {
TestSynchronized.test2();
}
},"test2"); thread2.start();
thread1.start();
}
}

  结果:

  

补充:

  面试的一道题:

    一个只被synchronized修饰的方法fun(),现有两个对象a,b,分别是两个线程t1,t2

    ①a.fun()和b.fun()可以同时进行吗?

      答:可以,因为是两个为不同的对象,对象的创建是以类为模板的,所以这两个对象中都会有自己的fun()方法,所以两个线程开启后会交替进行,如上面的二2

    ②回答完可以后,怎么可以让两个分开进行即一个完了之后再进行另一个?

      答:给方法加上static关键字,static锁住了类,此时锁为“类锁”,所以虽然对象不一样但是类都是一样的,所以简单说就是一个类两个线程调用一个方法,肯定是一个执行完再执行另一个

  

  

    

  

    

最新文章

  1. jQuery LigerUI系列:ligerComboBox
  2. java 遍历arrayList的四种方法
  3. hive内部表、外部表、分区表、视图
  4. Qt 自定义 滚动条 样式(模仿QQ)
  5. celery 学习笔记 01-介绍
  6. java 考试试题
  7. python 利用imap接收邮件,并保存附件
  8. 关于rsync的密码问题
  9. karma note
  10. ORACLE存储过程笔记3
  11. MFC自绘控件学习总结第二贴
  12. Windows Internals 笔记——线程优先级
  13. springMVC DispatcherServlet类关系图
  14. JDK文档中关于Semaphore的正确使用以及使用场景
  15. svn 从文件上次修改以来没有任何文件修改或加入。
  16. vs2010将写好的软件打包安装包经验
  17. 凸优化(Convex Optimization)浅析
  18. 【手机自动化测试】monkey测试
  19. 彻底解决_OBJC_CLASS_$_某文件名", referenced from:问题(转)
  20. 深度解析JQuery Dom元素操作技巧

热门文章

  1. C语言数组排序——冒泡排序、选择排序、插入排序
  2. Java程序员备战“金九银十”必备的面试技巧(附携程Java岗面试题)
  3. 认识Redies
  4. 集成Ribbon的客户端调用工具——Feign
  5. 实现API管理系统的几个重要关键词
  6. (通俗易懂小白入门)字符串Hash+map判重——暴力且优雅
  7. SpringMVC源码分析6:SpringMVC的视图解析原理
  8. Unity 自定义Inspector面板时的数据持久化问题
  9. Unity/C#基础复习(5) 之 浅析观察者、中介者模式在游戏中的应用与delegate原理
  10. 如何在Python中表示一个对象