【Java】同步 例子
2017-06-24 14:25
197 查看
之前记录了synchronized的基本用法,分为对象和类,以及方法和块。下面是一些结论。
1.方发锁和类锁不是同一个锁。这也是今日头条之前面试过的一个问题。
class Business{
public synchronized void f(){
System.out.println("not static starts");
for(int i = 0; i < 100; i ++){
System.out.println(i);
}
System.out.println("not static ends");
}
public static synchronized void g(){
System.out.println("static starts");
for(int i = 0; i < 100; i ++){
System.out.println(i);
}
System.out.println("static ends");
}
}
public class TThread implements Runnable{
@Override
public void run() {
try{
for(int i = 0; i < 10000; i++){
System.out.println(i);
if(Thread.interrupted()){
throw new InterruptedException();
}
}
}catch(InterruptedException e){
System.out.println("break");
}
}
public static void main(String args[]){
Business b = new Business();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
b.f();
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
b.g();
}
});
t1.start();
t2.start();
}
}
两个线程同时调用了业务类中的一个静态方法和一个非静态方法,都是syn关键字修饰的。那么他们之间不会同步。
这就印证了类锁和对象锁是不同的锁。可以想象为两个锁,因此执行静态方法和非静态方法是无法同步的。互不干扰。因为得到对象锁,不妨碍别的线程得到类锁,得到类锁也不妨碍别的线程得到对象锁。
2.对于对象锁而言,
syn语句块(x){}和x对象调用syn的方法以及x对象调用它的方法中的syn(this){}块之间是同步的。这三种情况。
class Business{
public synchronized void f1(){
System.out.println(Thread.currentThread().getName() + ":f1 starts");
for(int i = 0; i < 3; i ++){
System.out.println(i);
}
System.out.println(Thread.currentThread().getName() + ":f1 ends");
}
public void f2(){
synchronized(this){
System.out.println(Thread.currentThread().getName() + ":f2 starts");
for(int i = 0; i < 3; i ++){
System.out.println(i);
}
System.out.println(Thread.currentThread().getName() + ":f2 ends");
}
}
}
public class TThread implements Runnable{
Business b;
public TThread(Business b){
this.b=b;
}
@Override
public void run() {
f3();
}
public void f3(){
synchronized(b){
System.out.println(Thread.currentThread().getName() + ":f3 starts");
for(int i = 0; i < 3; i ++){
System.out.println(i);
}
System.out.println(Thread.currentThread().getName() + ":f3 ends");
}
}
public static void main(String args[]){
Business b = new Business();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
b.f1();
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
b.f2();
}
});
Thread t3 = new Thread(new TThread(b));
t1.start();
t2.start();
t3.start();
}
}
结果:
3.同步方法,在子类中重写,如果没有指定syn,则不会同步。如果子类没有重写,则会同步。
class Business{
public synchronized void f1(){
System.out.println(Thread.currentThread().getName() + ":f1 starts");
for(int i = 0; i < 30; i ++){
System.out.println(i);
}
System.out.println(Thread.currentThread().getName() + ":f1 ends");
}
}
class Sub extends Business{
@Override
public void f1(){
System.out.println(Thread.currentThread().getName() + ":f1 starts");
for(int i = 0; i < 30; i ++){
System.out.println(i);
}
System.out.println(Thread.currentThread().getName() + ":f1 ends");
}
}
public class TThread implements Runnable{
public static void main(String args[]){
Business b = new Sub();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
b.f1();
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
b.f1();
}
});
t1.start();
t2.start();
}
@Override
public void run() {
}
}
结果:
4.锁对象的改变;
如果把syn块内的对象引用指向别的对象,那么前后的对象锁就不同了,两个线程获取的锁也不同,最后就不会同步了。
class Business{
String lock = "123";
public void f1(){
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + ":f1 starts");
lock = "345";
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":f1 ends");
}
}
}
public class TThread implements Runnable{
public static void main(String args[]){
Business b = new Business();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
b.f1();
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
b.f1();
}
});
t1.start();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
}
@Override
public void run() {
}
}
t1先运行,run方法内部把锁对象改变了,这样t2申请的锁是另一个锁,于是可以直接执行。
5.死锁例子:
class Business {
String lock1;
String lock2;
Business(String s1, String s2){
lock1 = s1;
lock2 = s2;
}
public void f1(){
synchronized (lock1) {
System.out.println(Thread.currentThread().getName() + ":f1 starts");
synchronized (lock2) {
System.out.println(Thread.currentThread().getName() + ":f1 inner starts");
System.out.println(Thread.currentThread().getName() + ":f1 inner ends");
}
System.out.println(Thread.currentThread().getName() + ":f1 ends");
}
}
public void f2() {
synchronized (lock2) {
System.out.println(Thread.currentThread().getName() + ":f1 starts");
synchronized (lock1) {
System.out.println(Thread.currentThread().getName() + ":f1 inner starts");
System.out.println(Thread.currentThread().getName() + ":f1 inner ends");
}
System.out.println(Thread.currentThread().getName() + ":f1 ends");
}
}
}
public class TThread implements Runnable{
public static void main(String args[]){
Business b = new Business("123", "456");
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
b.f1();
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
b.f2();
}
});
t1.start();
t2.start();
}
@Override
public void run() {
}
}
1.方发锁和类锁不是同一个锁。这也是今日头条之前面试过的一个问题。
class Business{
public synchronized void f(){
System.out.println("not static starts");
for(int i = 0; i < 100; i ++){
System.out.println(i);
}
System.out.println("not static ends");
}
public static synchronized void g(){
System.out.println("static starts");
for(int i = 0; i < 100; i ++){
System.out.println(i);
}
System.out.println("static ends");
}
}
public class TThread implements Runnable{
@Override
public void run() {
try{
for(int i = 0; i < 10000; i++){
System.out.println(i);
if(Thread.interrupted()){
throw new InterruptedException();
}
}
}catch(InterruptedException e){
System.out.println("break");
}
}
public static void main(String args[]){
Business b = new Business();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
b.f();
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
b.g();
}
});
t1.start();
t2.start();
}
}
两个线程同时调用了业务类中的一个静态方法和一个非静态方法,都是syn关键字修饰的。那么他们之间不会同步。
这就印证了类锁和对象锁是不同的锁。可以想象为两个锁,因此执行静态方法和非静态方法是无法同步的。互不干扰。因为得到对象锁,不妨碍别的线程得到类锁,得到类锁也不妨碍别的线程得到对象锁。
2.对于对象锁而言,
syn语句块(x){}和x对象调用syn的方法以及x对象调用它的方法中的syn(this){}块之间是同步的。这三种情况。
class Business{
public synchronized void f1(){
System.out.println(Thread.currentThread().getName() + ":f1 starts");
for(int i = 0; i < 3; i ++){
System.out.println(i);
}
System.out.println(Thread.currentThread().getName() + ":f1 ends");
}
public void f2(){
synchronized(this){
System.out.println(Thread.currentThread().getName() + ":f2 starts");
for(int i = 0; i < 3; i ++){
System.out.println(i);
}
System.out.println(Thread.currentThread().getName() + ":f2 ends");
}
}
}
public class TThread implements Runnable{
Business b;
public TThread(Business b){
this.b=b;
}
@Override
public void run() {
f3();
}
public void f3(){
synchronized(b){
System.out.println(Thread.currentThread().getName() + ":f3 starts");
for(int i = 0; i < 3; i ++){
System.out.println(i);
}
System.out.println(Thread.currentThread().getName() + ":f3 ends");
}
}
public static void main(String args[]){
Business b = new Business();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
b.f1();
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
b.f2();
}
});
Thread t3 = new Thread(new TThread(b));
t1.start();
t2.start();
t3.start();
}
}
结果:
3.同步方法,在子类中重写,如果没有指定syn,则不会同步。如果子类没有重写,则会同步。
class Business{
public synchronized void f1(){
System.out.println(Thread.currentThread().getName() + ":f1 starts");
for(int i = 0; i < 30; i ++){
System.out.println(i);
}
System.out.println(Thread.currentThread().getName() + ":f1 ends");
}
}
class Sub extends Business{
@Override
public void f1(){
System.out.println(Thread.currentThread().getName() + ":f1 starts");
for(int i = 0; i < 30; i ++){
System.out.println(i);
}
System.out.println(Thread.currentThread().getName() + ":f1 ends");
}
}
public class TThread implements Runnable{
public static void main(String args[]){
Business b = new Sub();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
b.f1();
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
b.f1();
}
});
t1.start();
t2.start();
}
@Override
public void run() {
}
}
结果:
4.锁对象的改变;
如果把syn块内的对象引用指向别的对象,那么前后的对象锁就不同了,两个线程获取的锁也不同,最后就不会同步了。
class Business{
String lock = "123";
public void f1(){
synchronized (lock) {
System.out.println(Thread.currentThread().getName() + ":f1 starts");
lock = "345";
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":f1 ends");
}
}
}
public class TThread implements Runnable{
public static void main(String args[]){
Business b = new Business();
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
b.f1();
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
b.f1();
}
});
t1.start();
try {
Thread.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
t2.start();
}
@Override
public void run() {
}
}
t1先运行,run方法内部把锁对象改变了,这样t2申请的锁是另一个锁,于是可以直接执行。
5.死锁例子:
class Business {
String lock1;
String lock2;
Business(String s1, String s2){
lock1 = s1;
lock2 = s2;
}
public void f1(){
synchronized (lock1) {
System.out.println(Thread.currentThread().getName() + ":f1 starts");
synchronized (lock2) {
System.out.println(Thread.currentThread().getName() + ":f1 inner starts");
System.out.println(Thread.currentThread().getName() + ":f1 inner ends");
}
System.out.println(Thread.currentThread().getName() + ":f1 ends");
}
}
public void f2() {
synchronized (lock2) {
System.out.println(Thread.currentThread().getName() + ":f1 starts");
synchronized (lock1) {
System.out.println(Thread.currentThread().getName() + ":f1 inner starts");
System.out.println(Thread.currentThread().getName() + ":f1 inner ends");
}
System.out.println(Thread.currentThread().getName() + ":f1 ends");
}
}
}
public class TThread implements Runnable{
public static void main(String args[]){
Business b = new Business("123", "456");
Thread t1 = new Thread(new Runnable(){
@Override
public void run() {
b.f1();
}
});
Thread t2 = new Thread(new Runnable(){
@Override
public void run() {
b.f2();
}
});
t1.start();
t2.start();
}
@Override
public void run() {
}
}
相关文章推荐
- Java线程同步的例子
- 请给一个java线程同步的例子
- JAVA线程同步中wait()和notify()简洁例子
- 反编译:java代码中含有同步和异常的反编译前后代码对照的一个例子(xiongjy)
- java线程同步入门例子
- 关于取款问题 java同步简单的小例子
- 学习和理解JAVA线程同步--生产者与消费者例子
- JAVA线程同步中wait()和notify()简洁例子
- 理解 JAVA线程同步及其中中wait()和notify()简洁例子
- java学习7:银行存取款的例子,主要涉及对象同步问题,类似于数据库存取款,数据一致性问题
- java线程同步简单例子
- java线程同步简单例子
- java多进程 -CD7-孙鑫-(4)-同步方法,同步块,售票例子
- JAVA多线程互斥同步例子
- Java同步Socket通信例子(线程方式) ,完整版
- 同步,异步,阻塞,非阻塞的Java例子
- 学习和理解JAVA线程同步--生产者与消费者例子
- The Java™ Tutorials — Concurrency :A Synchronized Class Example 一个同步类的例子
- java线程同步问题(一个理解wait()与notify()的例子)
- ajax 同步调用 返回字符串 java例子(全)及 从后台返回中文乱码解决方法