package testSynchronized;

/**
*
* 当使用this也就是该文件中的testclass对象作为对象锁时,
* 两个线程都使用该对象锁访问该对象的同步代码块,
* 是顺序执行的,
* 也就是说当一个线程使用testclass对象对这段同步代码块上锁了以后,
* 另一个线程无法再使用testclass对象进入该同步代码块
* 理解:
* 因为该锁标记对象已经被标记为正在使用,所以只能排队
*
*/
class TestClass {
public void f(){
synchronized(this){
for(int i = 0 ; i < 1000 ; i ++){
System.out.println("i: " + i );
}
}
}
}
class ThreadTest extends Thread {
private TestClass testclass ;
public ThreadTest(TestClass testclass) {
this.testclass = testclass ;
}
@Override
public void run() {
testclass.f();
}
}
public class TestSynchroinzed {
public static void main(String[] args) {
TestClass testclass = new TestClass() ;
ThreadTest thread1 = new ThreadTest(testclass) ;
ThreadTest thread2 = new ThreadTest(testclass) ;
thread1.start();
thread2.start();
}
}

在来一个:

package testSynchronized;
/**
*
* 在该类中测试两个线程使用不同的锁对象,观察能不能同时访问一个同步代码块
*
* 出现的结果和TestSynchronized相反。这两个线程可以同时进入该同步代码块执行。
*
* why ???????
*
* 测试结果表明:
* 使用同一对象锁的多个线程需要排队访问
* 使用不同对象锁的多个线程可以同时访问(完全是不同的对象,不同的内存空间,当然不存在线程问题)
*
* 似乎明白了:
* 使用this作为锁标记,当一个线程使用这个锁标记锁住某些
* (可以使用一个线程同时访问使用一个对象标记锁的多个同步代码块,
* 那么这个线程就使用该对象锁住了多个同步代码块)代码块后,
* 其他的线程准备执行这个对象的这个同步代码块时,
* 会被告知这个this对象正在被使用锁住一些同步代码,还没有被释放,所以无法使用该锁进入同步代码块。
* 只有使用该锁锁住的所有同步代码块都执行结束的后,
* 其他的线程才能够重新使用该对象作为锁标记进入同步代码块
*
* 但是如果调用的就是不同的对象方法,
* 那么就不会存在同步的问题,
* 因为完全是两个不同的方法,不同的内存空间。
*/
class TestClass1 {
public void f(){
synchronized(this){
while(true);
}
}
public void f2(){
synchronized(this){
for(int i = 0 ; i < 100 ; i ++){
System.out.println("################");
}
}
}
}
class ThreadTest1 extends Thread {
private TestClass1 testclass ;
public ThreadTest1(TestClass1 testclass) {
this.testclass = testclass ;
}
@Override
public void run() {
testclass.f();
}
}
class ThreadTest2 extends Thread {
private TestClass1 testclass ;
public ThreadTest2(TestClass1 testclass) {
this.testclass = testclass ;
}
@Override
public void run() {
testclass.f2();
}
}
public class TestSynchronized2 {
public static void main(String[] args) {
TestClass1 testclass = new TestClass1() ;
TestClass1 testclass2 = new TestClass1() ;
ThreadTest1 thread1 = new ThreadTest1(testclass) ;
ThreadTest2 thread2 = new ThreadTest2(testclass) ;
thread1.start();
thread2.start();
}
}
package test;

/**
*
* 测试同步对象使用Class对象
*
* 总结: 注:每一个对象都有且仅有一个对象锁
* 1. 当同步代码块中使用的对象是一个类的普通对象, 那么当一个线程进入该同步代码块
* (或同步方法,区别不大,只是同步方法默认使用的锁对象是this) 并获取该对象的锁后(前提是该对象的锁是空闲的), 其他线程使用同一锁对象 (例如:
* 当两个线程使用同一对象并都调用该对象的一个同步方法时) 无法进入该同步代码块, 因为该代码块的锁对象的锁已经被先来的线程占用
* (注意,是该锁对象的锁,每一个对象都有唯一的一个锁,你能否进入同步代码块的唯一条件是你有没有获得锁对象的锁),现在的情况是,
* 一个线程已经占用了同步代码块的锁对象的锁,那么锁对象的其他非同步方法可以被其他线程访问(前提是该对象有非同步方法),
* 该锁对象的其他同步方法不能被其他线程访问。
*
* 2. 当同步代码块使用的锁对象是Class对象时(例如: TestClass.class,同步静态方法和使用Class对象的同步代码块的效果是一样的)。
* 当一个线程进入同步代码块(或者调用了静态同步方法)时,它获取了该Class对象的锁,那么其他的线程将不能访问该类的同步静态方法,
* 非同步静态方法可以正常访问 。
*/ class TestClass {
/**
* 一个线程访问f,一个线程访问staticF,理论上当第一个线程访问f时就会获得TestClass.class对象锁
* 那么另一个线程无法访问静态方法。
*/
public synchronized static void staticF() {
System.out.println("执行staticF");
} public void f() {
synchronized (TestClass.class) {
System.out.println("调用f()方法 ");
// 使用无限循环让当前线程一直占用TestClass.class对象锁
while (true)
;
}
} /**
* 该方法的作用是测试当一个线程获得了某个对象的锁后, 其他的线程能不能访问该对象的非同步方法或者同步代码块
*/ public void f3() {
synchronized (this) {
System.out.println("执行了f3()");
/**
* 下面是无限循环,目的是让当前线程一直占用着this这个对象的锁,
* 以查看其他线程能不能访问f4()这个非同步方法和f5()这个同步方法
*/
while (true)
;
}
} public void f4() {
System.out.println("执行了非同步方法f4()");
} public synchronized void f5() {
System.out.println("执行了非同步方法f5()");
}
} class Thread1 extends Thread {
private TestClass testclass; public Thread1(TestClass testclass) {
this.testclass = testclass;
} @Override
public void run() {
testclass.f();
}
} class Thread2 extends Thread {
@Override
public void run() {
TestClass.staticF();
}
} class Thread3 extends Thread {
private TestClass testclass; public Thread3(TestClass testclass) {
this.testclass = testclass;
} @Override
public void run() {
testclass.f3();
}
} class Thread4 extends Thread {
private TestClass testclass; public Thread4(TestClass testclass) {
this.testclass = testclass;
} @Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
testclass.f4();
}
} class Thread5 extends Thread {
private TestClass testclass; public Thread5(TestClass testclass) {
this.testclass = testclass;
} @Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
testclass.f5();
}
} public class Test {
public static void main(String[] args) {
TestClass testclass = new TestClass();
/*
* Thread1 thread1 = new Thread1(testclass) ; Thread2 thread2 = new
* Thread2() ; thread1.start(); thread2.start();
*/
Thread3 thread3 = new Thread3(testclass);
// Thread4 thread4 = new Thread4(testclass) ;
Thread5 thread5 = new Thread5(testclass);
thread3.start();
// thread4.start() ;
thread5.start(); }
}

关于java多线程的更多相关文章

  1. 40个Java多线程问题总结

    前言 Java多线程分类中写了21篇多线程的文章,21篇文章的内容很多,个人认为,学习,内容越多.越杂的知识,越需要进行深刻的总结,这样才能记忆深刻,将知识变成自己的.这篇文章主要是对多线程的问题进行 ...

  2. Java多线程基础知识篇

    这篇是Java多线程基本用法的一个总结. 本篇文章会从一下几个方面来说明Java多线程的基本用法: 如何使用多线程 如何得到多线程的一些信息 如何停止线程 如何暂停线程 线程的一些其他用法 所有的代码 ...

  3. Java多线程系列--“JUC锁”03之 公平锁(一)

    概要 本章对“公平锁”的获取锁机制进行介绍(本文的公平锁指的是互斥锁的公平锁),内容包括:基本概念ReentrantLock数据结构参考代码获取公平锁(基于JDK1.7.0_40)一. tryAcqu ...

  4. Java多线程系列--“JUC锁”04之 公平锁(二)

    概要 前面一章,我们学习了“公平锁”获取锁的详细流程:这里,我们再来看看“公平锁”释放锁的过程.内容包括:参考代码释放公平锁(基于JDK1.7.0_40) “公平锁”的获取过程请参考“Java多线程系 ...

  5. Java多线程--让主线程等待子线程执行完毕

    使用Java多线程编程时经常遇到主线程需要等待子线程执行完成以后才能继续执行,那么接下来介绍一种简单的方式使主线程等待. java.util.concurrent.CountDownLatch 使用c ...

  6. Java多线程 2 线程的生命周期和状态控制

    一.线程的生命周期 线程状态转换图: 1.新建状态 用new关键字和Thread类或其子类建立一个线程对象后,该线程对象就处于新生状态.处于新生状态的线程有自己的内存空间,通过调用start方法进入就 ...

  7. java 多线程 1 线程 进程

    Java多线程(一).多线程的基本概念和使用 2012-09-10 16:06 5108人阅读 评论(0) 收藏 举报  分类: javaSE综合知识点(14)  版权声明:本文为博主原创文章,未经博 ...

  8. 一起阅读《Java多线程编程核心技术》

    目录 第一章 Java多线程技能 (待续...)

  9. 第一章 Java多线程技能

    1.初步了解"进程"."线程"."多线程" 说到多线程,大多都会联系到"进程"和"线程".那么这两者 ...

  10. java从基础知识(十)java多线程(下)

    首先介绍可见性.原子性.有序性.重排序这几个概念 原子性:即一个操作或多个操作要么全部执行并且执行的过程不会被任何因素打断,要么都不执行. 可见性:一个线程对共享变量值的修改,能够及时地被其它线程看到 ...

随机推荐

  1. 通过PHP扩展phpredis操作redis

    我们使用phpredis,这个扩展能让你用PHP操作redis. 源码下载: phpize ./configure ); var_dump($result); echo $redis->get( ...

  2. super一些要点

    package o6; class Grandparent { public Grandparent() { System.out.println("GrandParent Created. ...

  3. 黑客语(Leet)

    黑客语(Leet)   Leet是从网络发展起来的一种文字书写方式.通常将英语中的字母替换为数字和特殊符号.这种方式被很多黑客组织所使用.由于具有隐密性,所以它也广泛被用于密码中.使用Leet书写的密 ...

  4. thymeleaf 基本表达式

    Thymeleaf 基本表达式 如需了解thymeleaf以及thymeleaf整合spring,请参考<Thymeleaf模板引擎使用>.<Thymeleaf 集成spring&g ...

  5. Shell 编程基础之 Until 练习

    一.语法 until [ condition ] # 和while相反,当 condition 条件成立时,就终止回圈, 否则就持续进行回圈的程序段 do #执行内容 done 二.练习 输入用户输入 ...

  6. sparklyr包--实现R与Spark接口

    1.sparklyr包简介 Rstudio公司发布的sparklyr包具有以下几个功能: 实现R与Spark的连接: sparklyr包提供了一个完整的dplyr后端,可筛选并聚合Spark数据集,接 ...

  7. JQuery validate验证 自定义

    http://www.w3cschool.cc/jquery/jquery-plugin-validate.html http://blog.163.com/zhao_jinggui/blog/sta ...

  8. BZOJ2769 : YY的快速排序

    将数字离散化并去重,则对于一对逆序对$i<j$,$a_i>a_j$,贡献为$\frac{2}{a_i-a_j+1}$,因此只要对于每个差值统计出对应的逆序对个数即可. 将序列分块,块内平方 ...

  9. BZOJ3562 : [SHOI2014]神奇化合物

    可以发现,从头到尾有一堆点是始终连在一起的,所以把没被删掉的一开始就有的边都加上后求出每个联通块, 缩完点后我们发现,边数也减少得差不多了,剩下的就直接暴力. #include<cstdio&g ...

  10. 目前quanben评十大哲学家

    排名分先后,包含时间.地区和主要正面成就以及其他代表人物. 1. 伊曼努尔·康德:十八世纪:东普鲁士:理性的界限,现象和本体分立以及主体的地位2. 柏拉图:公元前三四百年:古希腊:理想(念)世界3. ...