精华内容
下载资源
问答
  • CriticalSeciton实现线程同步 vc++ 临界区使用 线程同步问题
  • 今天小编就为大家分享一篇关于C#使用Interlocked实现线程同步,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
  • 如何实现线程同步

    2018-12-14 19:33:48
    实现线程同步有三种方式: 1 同步代码块 synchronized(锁资源) { 需要同步执行的代码 } 解释:同步代码块会对资源加上资源锁,多线程访问的时候,需要先获取锁资源,并且没有拿到锁资源的线程需要等待锁资源的释放 ...

    实现线程同步有三种方式:
    1 同步代码块
    synchronized(锁资源) {
    需要同步执行的代码
    }
    解释:同步代码块会对资源加上资源锁,多线程访问的时候,需要先获取锁资源,并且没有拿到锁资源的线程需要等待锁资源的释放
    锁资源:同一个锁资源才能实现线程同步
    三种锁资源:
    A this锁
    B xx.class锁
    C 字符串常量锁 String haha = “asd”;
    测试类:

     public static void main(String[] args) throws Exception{	
    	test1();	
    }
     public static void test1() throws Exception {
    	
    	Ticket ticket = new Ticket();
    	
    	new Thread(ticket,"窗口A").start();
    	new Thread(ticket,"窗口B").start();
    	new Thread(ticket,"窗口C").start();   	
    } 
    

    Ticket类:

    public class Ticket implements Runnable{	
    private static int  count = 50;
    //同步代码块
    	@Override
    	public void run() {		
    		while (count > 0) {
    			synchronized (this) {
    			try {
    				Thread.sleep(100);//线程休眠
    					if(count>0){
    						System.out.println(Thread.currentThread().getName()+"售票,出售第:"+count--+"张票");
    					}
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}
    			}
    		}	
    	}
    }
    

    2 同步方法

    public class Ticket implements Runnable{
    	private static int  count = 50;
    	//同步方法
    	 @Override
    	public synchronized void run() {	
    		while (count > 0) {
    			try {		
    				Thread.sleep(100);
    				System.out.println(Thread.currentThread().getName()+"售票,出售第:"+count--+"张票");
    			} catch (InterruptedException e) {
    				// TODO Auto-generated catch block
    				e.printStackTrace();
    			}	
    		}		
    	}
    }
    

    非静态同步方法使用的是this锁 相当于synchronized(this){ }
    静态同步方法使用的是类锁 相当于synchronized(xx.class){ }
    3 同步锁

    public class Ticket implements Runnable{
    private static int  count = 50;
    
    private Lock  lock = new ReentrantLock();  
      public void run() {
    	while (count > 0) {
    		 try {
    			Thread.sleep(100);
    			lock.lock();//执行开始之前加锁
    			if(count > 0) {
    				System.out.println(Thread.currentThread().getName()+"售票,出售第:"+count--+"张票");							
    			}						
    		} catch (InterruptedException e) {
    			// TODO Auto-generated catch block
    			e.printStackTrace();
    		} finally{
    			lock.unlock();//解锁
    		}				    
    	}	
      }
    }
    
    展开全文
  • 主要介绍了Java实现线程同步方法及原理详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
  • 利用synchronized实现线程同步

    千次阅读 2018-03-26 22:36:13
    (2)多线程同步原因:一个多线程的程序如果是通过Runnable接口实现的,则意味着类中的属性将被多个线程共享,由此引出资源的同步问题,即当多个线程要操作同一资源时,有可能出现错误。(3)实现线程同步的方式...


    一、前期基础知识储备

    (1)线程同步的定义:多线程之间的同步。

    (2)多线程同步原因:一个多线程的程序如果是通过Runnable接口实现的,则意味着类中的属性将被多个线程共享,由此引出资源的同步问题,即当多个线程要操作同一资源时,有可能出现错误。

    (3)实现多线程同步的方式——引入同步机制:在线程使用一个资源时为其加锁,这样其他的线程便不能访问那个资源了,直到解锁后才可以访问。——这样做的结果,所有线程间会有资源竞争,但是所有竞争的资源是同步的,刷新的,动态的,不会因为线程间的竞争,导致资源“过度消耗”或者“虚拟消耗”。

    上代码,具体展示“过度消耗/虚拟消耗”问题:

    public class TestTicketRunnable{
        public static void main(String[] a){
            TicketThread tThread = new TicketThread();
            new Thread(tThread).start();
            new Thread(tThread).start();
            new Thread(tThread).start();
        }
    };
    class TicketThread implements Runnable {
        private int ticket = 5;
        public void run(){
            for (int i = 0; i < 5; i++){
                if (ticket > 0){
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "卖票:ticket = " + ticket--);
                }
            }
        }
    };

    运行结果:Thread-0卖票:ticket = 5

    Thread-2卖票:ticket = 5 //虚拟消耗

    Thread-1卖票:ticket = 4

    Thread-1卖票:ticket = 2

    Thread-2卖票:ticket = 3

    Thread-0卖票:ticket = 3 //虚拟消耗

    Thread-0卖票:ticket = -1 //过度消耗

    Thread-1卖票:ticket = 1

    Thread-2卖票:ticket = 0

    如上所见,票一共5张,三个线程调用买票,线程1网上卖了售票第1张,紧接着线程2线下也卖了“第一张”出现了“虚拟消耗”的问题;线程3黄牛党卖了最后1张票,线程1网上又卖了最后1张,出现了“过度消耗”的问题,这两种问题都是实际生活中不可能发生的,但是在这个3个线程执行中却出现了,那一定是有问题的,问题的根源就在于,三个渠道的“售票员”不在一个频道上办事,或者说没有相互之间同步所共享的资源,导致这一问题的根本原因,就是相互之间实现方式不同步。

    二、使用synchronized实现同步机制

    synchronized关键字:Java语言的关键字,可用来给对象和方法或者代码块加锁,当它锁定一个方法或者一个代码块的时候,同一时刻最多只有一个线程执行这段代码。当两个并发线程访问同一个对象object中的这个加锁同步代码块时,一个时间内只能有一个线程得到执行。另一个线程必须等待当前线程执行完这个代码块以后才能执行该代码块。它包括两种用法:synchronized 方法和 synchronized 块。

    即实现线程间同步的方式有两种:

    ①使用synchronized同步代码块;

    ②使用synchronized关键字创建synchronized()方法

    下面分别进行解析,对上面售票的代码进行改造:

    ①代码——使用synchronized同步代码块

    class TicketThread implements Runnable {
        private int ticket = 5;
        public void run(){
            for (int i = 0; i < 5; i++){
                synchronized(this){
                    if (ticket > 0){
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "卖票:ticket = " + ticket--);
               	}
               }
           }
        }
    }

    ②代码——使用synchronized关键字创建synchronized()方法

    class TicketThreadMethod implements Runnable {
        private int ticket = 5;
        public void run(){
            for (int i = 0; i < 5; i++){
                this.sale();
            }
        }
        public synchronized void sale(){
                if (ticket > 0){
                    try {
                        Thread.sleep(300);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "卖票:ticket = " + ticket--);
                }
        }
    }

    三、synchronized方法和synchronized同步代码块的区别:

    • synchronized同步代码块只是锁定了该代码块,代码块外面的代码还是可以被访问的。
    • synchronized方法是粗粒度的并发控制,某一个时刻只能有一个线程执行该synchronized方法。
    • synchronized同步代码块是细粒度的并发控制,只会将块中的代码同步,代码块之外的代码可以被其他线程同时访问。



    展开全文
  • 使用CEvent对象实现线程同步 MFC工程
  • 用信号量实现线程同步,多个线程共享一个资源。
  • 利用 CountDownLatch 类实现线程同步,而不用回调机制。详见我的博文 http://blog.csdn.net/kroclin/article/details/37956949
  • 线程同步实现

    2017-08-25 16:27:42
    vs实现线程同步,利用event和锁
  • Ruby线程实现经典的生产者消费者问题,用ruby中的Queue类实现线程同步问题。 代码如下:require “thread” puts “ProAndCon” queue = Queue.new #用队列Queue实现线程同步 producer = Thread.new do 10....
  • 内容索引:VC/C++源码,系统相关,线程,CMutex,同步 C++ 使用CMutex 类实现线程同步,将了解到声明线程函数,定义全局变量m_Sec,程序睡眠10秒,锁定临界区,对临界区进行解锁,输出变量等知识点。
  • linux中实现线程同步的6种方法

    万次阅读 多人点赞 2020-10-22 16:37:21
    linux线程同步的方法 下面是一个线程不安全的例子: #include<stdio.h> #include<pthread.h> int ticket_num=10000000; void *sell_ticket(void *arg) { while(ticket_num>0) { ticket_num--; }...

    linux线程同步的方法

    下面是一个线程不安全的例子:

    #include<stdio.h>
    #include<pthread.h>
    
    int ticket_num=10000000;
    
    void *sell_ticket(void *arg) {
        while(ticket_num>0) {
    	ticket_num--;
        }
    }
    
    int main() {
        pthread_t t1,t2,t3;
        pthread_create(&t1, NULL, &sell_ticket, NULL);
        pthread_create(&t2, NULL, &sell_ticket, NULL);
        pthread_create(&t3, NULL, &sell_ticket, NULL);
        pthread_join(t1, NULL);
        pthread_join(t2, NULL);
        pthread_join(t3, NULL);
        printf("ticket_num=%d\n", ticket_num);
        return 0;
    }
    

    运行结果如下:

    # gcc no_lock_demo.c -o no_lock_demo.out -pthread
    # ./no_lock_demo.out 
    ticket_num=-2
    

    最后运行的结果不是固定的,有可能是0、-1,如果有这个ticket_num变量代表是库存的话,那么就会出现库存为负数的情况,所以需要引入线程同步来保证线程安全。

    Linux下提供了多种方式来处理线程同步,最常用的是互斥锁、自旋锁、信号量。

    互斥锁

    互斥锁本质就是一个特殊的全局变量,拥有lock和unlock两种状态,unlock的互斥锁可以由某个线程获得,当互斥锁由某个线程持有后,这个互斥锁会锁上变成lock状态,此后只有该线程有权力打开该锁,其他想要获得该互斥锁的线程都会阻塞,直到互斥锁被解锁。

    互斥锁的类型:

    • 普通锁(PTHREAD_MUTEX_NORMAL):互斥锁默认类型。当一个线程对一个普通锁加锁以后,其余请求该锁的线程将形成一个 等待队列,并在该锁解锁后按照优先级获得它,这种锁类型保证了资源分配的公平性。一个 线程如果对一个已经加锁的普通锁再次加锁,将引发死锁;对一个已经被其他线程加锁的普 通锁解锁,或者对一个已经解锁的普通锁再次解锁,将导致不可预期的后果。

    • 检错锁(PTHREAD_MUTEX_ERRORCHECK):一个线程如果对一个已经加锁的检错锁再次加锁,则加锁操作返回EDEADLK;对一个已 经被其他线程加锁的检错锁解锁或者对一个已经解锁的检错锁再次解锁,则解锁操作返回 EPERM。

    • 嵌套锁(PTHREAD_MUTEX_RECURSIVE):该锁允许一个线程在释放锁之前多次对它加锁而不发生死锁;其他线程要获得这个锁,则当前锁的拥有者必须执行多次解锁操作;对一个已经被其他线程加锁的嵌套锁解锁,或者对一个已经解锁的嵌套锁再次解锁,则解锁操作返回EPERM。

    • 默认锁(PTHREAD_MUTEX_ DEFAULT):一个线程如果对一个已经加锁的默认锁再次加锁,或者虽一个已经被其他线程加锁的默 认锁解锁,或者对一个解锁的默认锁解锁,将导致不可预期的后果;这种锁实现的时候可能 被映射成上述三种锁之一。

    相关方法:

    
    // 静态方式创建互斥锁
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER; 
    
    // 动态方式创建互斥锁,其中参数mutexattr用于指定互斥锁的类型,具体类型见上面四种,如果为NULL,就是普通锁。
    int pthread_mutex_init (pthread_mutex_t* mutex,const pthread_mutexattr_t* mutexattr);
    
    int pthread_mutex_lock(pthread_mutex_t *mutex); // 加锁,阻塞
    int pthread_mutex_trylock(pthread_mutex_t *mutex); // 尝试加锁,非阻塞
    int pthread_mutex_unlock(pthread_mutex_t *mutex); // 解锁
    

    例子:

    #include<stdio.h>
    #include<pthread.h>
    
    int ticket_num=10000000;
    
    pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
    
    void *sell_ticket(void *arg) {
        while(ticket_num>0) {
    	pthread_mutex_lock(&mutex);
    	if(ticket_num>0) {
    	    ticket_num--;
    	}
    	pthread_mutex_unlock(&mutex);
        }
    }
    
    int main() {
        pthread_t t1,t2,t3;
        pthread_create(&t1, NULL, &sell_ticket, NULL);
        pthread_create(&t2, NULL, &sell_ticket, NULL);
        pthread_create(&t3, NULL, &sell_ticket, NULL);
        pthread_join(t1, NULL);
        pthread_join(t2, NULL);
        pthread_join(t3, NULL);
        printf("ticket_num=%d\n", ticket_num);
        return 0;
    }
    

    自旋锁

    自旋锁顾名思义就是一个死循环,不停的轮询,当一个线程未获得自旋锁时,不会像互斥锁一样进入阻塞休眠状态,而是不停的轮询获取锁,如果自旋锁能够很快被释放,那么性能就会很高,如果自旋锁长时间不能够被释放,甚至里面还有大量的IO阻塞,就会导致其他获取锁的线程一直空轮询,导致CPU使用率达到100%,特别CPU时间。

    相关方法:

    int pthread_spin_init(pthread_spinlock_t *lock, int pshared); // 创建自旋锁
    
    int pthread_spin_lock(pthread_spinlock_t *lock); // 加锁,阻塞
    int pthread_spin_trylock(pthread_spinlock_t *lock); // 尝试加锁,非阻塞
    int pthread_spin_unlock(pthread_spinlock_t *lock); // 解锁
    

    例子:

    #include<stdio.h>
    #include<pthread.h>
    
    int ticket_num=10000000;
    
    pthread_spinlock_t spinlock;
    
    void *sell_ticket(void *arg) {
        while(ticket_num>0) {
    	pthread_spin_lock(&spinlock);
    	if(ticket_num>0) {
    	    ticket_num--;
    	}
    	pthread_spin_unlock(&spinlock);
        }
    }
    
    int main() {
        pthread_spin_init(&spinlock, 0);
        pthread_t t1,t2,t3;
        pthread_create(&t1, NULL, &sell_ticket, NULL);
        pthread_create(&t2, NULL, &sell_ticket, NULL);
        pthread_create(&t3, NULL, &sell_ticket, NULL);
        pthread_join(t1, NULL);
        pthread_join(t2, NULL);
        pthread_join(t3, NULL);
        printf("ticket_num=%d\n", ticket_num);
        return 0;
    }
    

    信号量

    信号量是一个计数器,用于控制访问有限共享资源的线程数。

    相关方法:

    // 创建信号量
    // pshared:一般取0,表示调用进程的信号量。非0表示该信号量可以共享内存的方式,为多个进程所共享(Linux暂不支持)。
    // value:信号量的初始值,可以并发访问的线程数。
    int sem_init (sem_t* sem, int pshared, unsigned int value);
    
    int sem_wait (sem_t* sem); // 信号量减1,信号量为0时就会阻塞
    
    int sem_trywait (sem_t* sem); // 信号量减1,信号量为0时返回-1,不阻塞
    
    int sem_timedwait (sem_t* sem, const struct timespec* abs_timeout); // 信号量减1,信号量为0时阻塞,直到abs_timeout超时返回-1
    
    int sem_post (sem_t* sem); // 信号量加1
    

    例子:

    #include<stdio.h>
    #include<pthread.h>
    #include <semaphore.h>
    
    int ticket_num=10000000;
    
    sem_t sem;
    
    void *sell_ticket(void *arg) {
        while(ticket_num>0) {
    	sem_wait(&sem);
    	if(ticket_num>0) {
    	    ticket_num--;
    	}
    	sem_post(&sem);
        }
    }
    
    int main() {
        sem_init(&sem, 0, 1); // value=1表示最多1个线程同时访问共享资源,与互斥量等价
        pthread_t t1,t2,t3;
        pthread_create(&t1, NULL, &sell_ticket, NULL);
        pthread_create(&t2, NULL, &sell_ticket, NULL);
        pthread_create(&t3, NULL, &sell_ticket, NULL);
        pthread_join(t1, NULL);
        pthread_join(t2, NULL);
        pthread_join(t3, NULL);
        printf("ticket_num=%d\n", ticket_num);
        return 0;
    }
    

    条件变量

    条件变量可以让调用线程在满足特定条件的情况下运行,不满足条件时阻塞等待被唤醒,必须与互斥锁搭配使用。

    条件变量常用于生产者与消费者模型。

    相关方法:

    pthread_cond_t cond=PTHREAD_COND_INITIALIZER; // 创建条件变量,一个互斥锁可以对应多个条件变量
    
    int pthread_cond_wait (pthread_cond_t* cond,pthread_mutex_t* mutex); // 阻塞等待条件满足,同时释放互斥锁mutex
    
    int pthread_cond_timedwait (pthread_cond_t* cond,
        pthread_mutex_t* mutex,
        const struct timespec* abstime); // 带超时的阻塞等待条件满足,同时释放互斥锁mutex
    
    // 从条件变量cond中唤出一个线程,令其重新获得原先的互斥锁
    // 被唤出的线程此刻将从pthread_cond_wait函数中返回,但如果该线程无法获得原先的锁,则会继续阻塞在加锁上。
    int pthread_cond_signal (pthread_cond_t* cond);
    
    // 从条件变量cond中唤出所有线程
    int pthread_cond_broadcast (pthread_cond_t* cond);
    

    例子:

    #include<stdio.h>
    #include<pthread.h>
    
    int max_buffer=10;
    int count=0;
    
    pthread_mutex_t mutex=PTHREAD_MUTEX_INITIALIZER;
    pthread_cond_t notempty=PTHREAD_COND_INITIALIZER;
    pthread_cond_t notfull=PTHREAD_COND_INITIALIZER;
    
    void *produce(void *args) {
        while(1) {
            pthread_mutex_lock(&mutex);
            while(count == max_buffer) {
                printf("buffer is full, wait...\n");
                pthread_cond_wait(&notfull, &mutex);
            }
            printf("produce ...\n");
            count++;
            sleep(1);
            pthread_cond_signal(&notempty);
            pthread_mutex_unlock(&mutex);
        }
    
    }
    
    void *consumer(void *args) {
        while(1) {
            pthread_mutex_lock(&mutex);
            while(count == 0) {
                printf("buffer is empty, wait...\n");
                pthread_cond_wait(&notempty, &mutex);
            }
            printf("consumer ...\n");
            count--;
            sleep(1);
            pthread_cond_signal(&notfull);
            pthread_mutex_unlock(&mutex);
        }
    
    }
    
    int main() {
        pthread_t t1,t2,t3,t4;
        pthread_create(&t1, NULL, &produce, NULL);
        pthread_create(&t2, NULL, &produce, NULL);
    
        pthread_create(&t3, NULL, &consumer, NULL);
        pthread_create(&t4, NULL, &consumer, NULL);
    
        pthread_join(t1, NULL);
        return 0;
    }
    

    读写锁

    读写锁可以有三种状态:读模式下加锁状态,写模式下加锁状态,不加锁状态。一次只有一个线程可以占有写模式的读写锁,但是多个线程可以同时占有读模式的读写锁。读写锁也叫做共享-独占锁,当读写锁以读模式锁住时,它是以共享模式锁住的,当它以写模式锁住时,它是以独占模式锁住的,读读共享,读写互斥。

    相关方法:

    // 创建读写锁
    pthread_rwlock_t rwlock=PTHREAD_RWLOCK_INITIALIZER;
    
    int pthread_rwlock_rdlock(pthread_rwlock_t *rwlock); // 加读锁,阻塞
    int pthread_rwlock_wrlock(pthread_rwlock_t *rwlock); // 加写锁,阻塞
    int pthread_rwlock_unlock(pthread_rwlock_t *rwlock); // 释放读锁或者写锁
    
    int pthread_rwlock_tryrdlock(pthread_rwlock_t *rwlock); // 尝试加读锁,非阻塞
    int pthread_rwlock_trywrlock(pthread_rwlock_t *rwlock); // 尝试加写锁,非阻塞
    

    例子:

    #include <stdio.h>
    #include <pthread.h>
    
    pthread_rwlock_t rwlock=PTHREAD_RWLOCK_INITIALIZER;
    
    void *read(void *arg) {
        while(1) {
            pthread_rwlock_rdlock(&rwlock);
            rintf("read message.\n");
            sleep(1);
            pthread_rwlock_unlock(&rwlock);
            sleep(1);
        }
    }
    void *write(void *arg) {
        while(1) {
            pthread_rwlock_wrlock(&rwlock);
            printf("write message.\n");
            sleep(1);
            pthread_rwlock_unlock(&rwlock);
            sleep(1);
        }
    }
    
    int main(int argc,char *argv[]) {
        pthread_t t1,t2,t3;
        pthread_create(&t1, NULL, &read, NULL);
        pthread_create(&t2, NULL, &read, NULL);
    
        pthread_create(&t3, NULL, &write, NULL);
    
        pthread_join(t1, NULL);
        return 0;
    }
    

    屏障

    屏障(barrier)是用户协调多个线程并行工作的同步机制。屏障允许每个线程等待,直到所有的合作线程都到达某一点,然后所有线程都从该点继续执行。pthread_join函数就是一种屏障,允许一个线程等待,直到另一个线程退出。但屏障对象的概念更广,允许任意数量的线程等待,直到所有的线程完成处理工作,而线程不需要退出,当所有的线程达到屏障后可以接着工作。

    相关方法:

    // 创建屏障
    int pthread_barrier_init(pthread_barrier_t *barrier,const pthread_barrrierattr_t *attr,unsigned int count)
    
    // 阻塞等待,直到所有线程都到达
    int pthread_barrier_wait(pthread_barrier_t *barrier)
    

    例子:

    #include <stdio.h>
    #include <pthread.h>
    
    pthread_barrier_t barrier;
    
    void *go(void *arg){
        sleep (rand () % 10);
        printf("%lu is arrived.\n", pthread_self());
        pthread_barrier_wait(&barrier);
        printf("%lu go shopping...\n", pthread_self());
    }
    
    int main() {
        pthread_barrier_init(&barrier, NULL, 3);
    
        pthread_t t1,t2,t3;
        pthread_create(&t1, NULL, &go, NULL);
        pthread_create(&t2, NULL, &go, NULL);
        pthread_create(&t3, NULL, &go, NULL);
    
        pthread_join(t1, NULL);
        return 0;
    }
    
    展开全文
  • 自定义Dictionary类如何在类内实现线程同步自定义Dictionary类如何在类内实现线程同步自定义Dictionary类如何在类内实现线程同步自定义Dictionary类如何在类内实现线程同步自定义Dictionary类如何在类内实现线程同步...
  • 上一篇说明了多线程是存在着问题的,起始就是多线程操作同一数据而不同步的问题。那么如果实现线程的同步呢?... 我们先用互斥内核对象实现线程同步。    互斥内核对象,能够确保线程拥有对单个资源

             上一篇说明了多线程是存在着问题的,起始就是多线程操作同一数据而不同步的问题。那么如果实现线程的同步呢?

             线程的同步有多种实现方式:

            互斥内核对象、事件内核对象、可等待的计数器内核对象、信号量内核对象和等待函数等等来实现线程的同步。

            我们先用互斥内核对象实现线程同步。

          

             互斥内核对象,能够确保线程拥有对单个资源的互斥访问权,互斥对象包含一个使用数量,一个线程ID和一个计数器。其中ID用于标识系统中的哪个线程当前拥有互斥对象,计数器用于指明该线程拥有互斥对象的次数。

    使用CreateMutext函数,创建或打开一个互斥对象,然后利用互斥对象完成线程间的同步。

    HANDLE CreateMutex(
         LPSECURITY_ATTRIBUTESl  pMutexAttributes, // 指向安全属性的指针
         BOOL  bInitialOwner, // 初始化互斥对象的所有者
         LPCTSTR  lpName // 指向互斥对象名的指针
    );
    参数 类型及说明
    lpMutexAttributes :

             可以使用NULL,表示使用默认的安全性。
    bInitialOwner
    :

              表示互斥对象的初始拥有者。如果为真,创建这个互斥对象的线程获得该对象的所有权,否则,该线程不获得该互斥对象的所有权。
    lpName
    :

              指定互斥体对象的名字。如果为NULL,则创建一个匿名的互斥对象。


           当结束后,使用ReleaseMutex函数进行释放指定对象的所有权。

    BOOL WIANPI ReleaseMutex(
        HANDLE hMutex
    );

          需要注意,线程只有主动请求共享对象的所有权才有可能获取到该所有权,我们可以通过WaitForSingleObject来实现

    DWORD WaitForSingleObject(
         HANDLE hHandle,
         DWORD dwMilliseconds
    );
             hHandle为句柄,此处为 hMutex的句柄,

            dwMilliseconds为指定时间间隔,单位为毫秒。如果指定一个非零值,函数处于等待状态直到hHandle标记的对象被触发,或者时间到了。如果dwMilliseconds为0,对象没有被触发信号,函数不会进入一个等待状态,它总是立即返回。如果dwMilliseconds为INFINITE,对象被触发信号后,函数才会返回。

           WaitForSingleObject函数用来检测hHandle事件的信号状态,在某一线程中调用该函数时,线程暂时挂起,如果在挂起的dwMilliseconds毫秒内,线程所等待的对象变为有信号状态,则该函数立即返回;如果超时时间已经到达dwMilliseconds毫秒,但hHandle所指向的对象还没有变成有信号状态,函数照样返回。参数dwMilliseconds有两个具有特殊意义的值:0和INFINITE。若为0,则该函数立即返回;若为INFINITE,则线程一直被挂起,直到hHandle所指向的对象变为有信号状态时为止。

       

    // ConsoleApplication1.cpp : 定义控制台应用程序的入口点。
    //
    
    #include "stdafx.h"
    #include <stdlib.h>
    #include <string.h>
    #include <windows.h>
    
    int tickets = 100;
    HANDLE hMutex;
    int idx = 0;
    
    DWORD  WINAPI ThreadProc1(LPVOID lpThreadParameter)
    {
    
    	while (TRUE)
    	{
    		WaitForSingleObject(hMutex, INFINITE);
    		if (tickets>0)
    		{
    			Sleep(1);
    			printf("thread1 ----  %d \n", tickets--);
    		}
    		else
    		{
    			break;
    		}
    
    		ReleaseMutex(hMutex);
    	}
    	return 0;
    }
    
    
    DWORD  WINAPI ThreadProc2(LPVOID lpThreadParameter)
    {
    
    	while (TRUE)
    	{
    	 	WaitForSingleObject(hMutex, INFINITE);
    		if (tickets > 0)
    		{
    			Sleep(1);
    			printf("thread2 ----  %d \n", tickets--);
    		}
    		else
    		{
    			break;
    		}
    		ReleaseMutex(hMutex);
    
    	}
    	return 0;
    }
    
    int _tmain(int argc, _TCHAR* argv[])
    {
     
    	//创建线程
    	HANDLE  h1 = CreateThread(NULL, 0, ThreadProc1, NULL, 0, NULL);
    	HANDLE  h2 = CreateThread(NULL, 0, ThreadProc2, NULL, 0, NULL);
    
    	CloseHandle(h1);
    	CloseHandle(h2);
    
    
    	//创建互斥对象
    	hMutex = CreateMutex(NULL, FALSE, NULL);
    	/*<pre name="code" class="html">        hMutex = CreateMutex(NULL, TRUE, NULL);  //如果第二个参数设置为true 那么此时互斥对象为主线程所有  
    ReleaseMutex(hMutex); //当第二参数的为True的时候 则需要使用该函数 进行释放互斥对象 只有释放后线程1和线程2才能获取 */system("pause");return 0;}
     
    


    展开全文
  • 实现线程同步的第一种方式是我们经常使用的lock关键字,它将包围的语句块标记为临界区,这样一次只有一个线程进入临界区并执行代码,接下来通过本文给大家介绍C#中实现线程同步lock关键字的用法详解,一起看看吧
  • 当使用多个线程来访问同一个数据时,非常容易出现线程安全问题,所以我们用同步机制来解决这些问题,本文将详细介绍,需要的朋友可以参考下
  • c++实现线程同步

    2015-09-10 10:36:54
    在windows平台上建立的c++多线程demo,利用信号量实现线程同步功能。
  • 利用mutex互斥变量实现线程同步机制,并输出循环1000000次所用的时间
  • 使用互斥对象(Mutex)实现线程同步。MFC工程
  • 多线程编程--5种方法实现线程同步

    千次阅读 2013-03-31 15:23:24
    1:用Interlocked系列函数实现线程同步; 2:用CRITICAL_SECTION及其系列函数实现线程同步; 3:用RTL_SRWLOCK及其系列函数实现线程同步; 4:用事件内核对象实现线程同步; 5:用信号量内核对象实现线程同步; ...
  • 在多线程对共享资源进行并发访问方面,JDK提供了synchronized关键字来进行线程同步实现多线程并发访问的线程安全。synchronized的作用主要体现在三个方面:(1)确保线程互斥地访问同步代码;(2)保证共享变量的...
  • 利用信号量实现线程同步

    千次阅读 2017-05-21 20:29:16
    信号量简单的说,信号量内核对象,也是多线程同步的一种机制,它可以对资源访问进行计数,包括最大资源计数和当前资源计数,是两个32位的值;另外,计数是以原子访问的方式进行,由操作系统维护; 最大资源计数,...
  • 最近小扁我被问到 实现线程同步有哪几种方法,而我只知道使用同步关键字synchronized来实现而已(⊙o⊙),,所以有必要来学习一下实现线程同步的几种方法;各位看官,若有非议(不接受反驳),请不吝赐教! 实现...
  • 使用临界区对象(CriticalSeciton)实现线程同步。MFC工程
  • 实现线程同步的几种方法

    万次阅读 2018-09-27 09:50:52
    因此引入多线程同步,也就是说多个线程只能一个对共享的资源进行更改,其他线程不能对数据进行修改。 如下一个两个线程对一个银行账户进行存钱的小实例,其中使用synchornized修饰方法实现线程的同步 代码如下: `...
  • Java 多线程 系列文章目录: Java 多线程(一)线程间的互斥和同步通信 Java 多线程(二)同步线程分组问题 ... Java 多线程(五)Lock 和 Condition 实现线程同步通信 Java 多线程(六)Semaphore 实...
  • 实现线程同步的几种方式总结

    万次阅读 多人点赞 2018-07-25 21:31:26
    在多线程线程的执行顺序是依靠哪个线程先获得到CUP的执行权谁就先执行,虽然说可以通过线程的优先权进行设置,但是他只是获取CUP执行权的概率高点,但是也不一定必须先执行。在这种情况下如何保证线程按照一定的...
  • 在iOS多线程中我们知道NSOperationQueue操作队列可以直接使用addDependency函数设置操作之间的依赖关系实现线程同步,还可以使用setMaxConcurrentOperationCount函数直接设置最大并发数量。那么在GCD中又是如何实现...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 679,066
精华内容 271,626
关键字:

怎样实现线程同步