Empresas
Empregos
  • Sobre nós
  • Soluções
    • Publicação de vagas
      Publique sua vaga e receba candidatos qualificados em 48h.
    • Avaliações de candidatos
      Mais de 500 testes técnicos e psicológicos, mais anti-fraude.
    • Headhunting
      Busca executiva personalizada do início ao fim.
    • Folha de Pagamento + EOR
      Dispersão de folha e EOR em mais de 15 países da LATAM.
  • Preços
  • Empregos

0

226
Visualizações
Does SemaphoreSlim(1, 1) ensures read and writes are flushed from caches like lock?

Extra question

Does SemaphoreSlim(1, 1) still ensures that I have the correct output 1000000, even if task1 and task2 run on 2 different cores?

Original question

Considering the following code snippet, does the _semaphore has the same effect as lock?

The outputs:

  1. using lock: 1000000
  2. _semaphore = new SemaphoreSlim(1, 1): 1000000 (I run the program 10 times and the results are the same)
  3. _semaphore = new SemaphoreSlim(10, 10): varies from 999998 to 999990 to 1000000, etc.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleApp1
{
    class Calculate
    {
        private int _val = 0;
        private object _addLock = new object();
        private SemaphoreSlim _semaphore = new SemaphoreSlim(1, 1);
        public int Val
        {
            get
            {
                return _val;
            }
        }

        public void IncreManyTimes()
        {
            for (int i = 0; i < 500000; ++i)
            {
                //lock(_addLock)
                //{
                //    _val = _val + 1;
                //}
                _semaphore.Wait();
                _val = _val + 1;
                _semaphore.Release();
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            Calculate calculate = new Calculate();
            Task.Run(() =>
            {
                Task task1 = Task.Run(() =>
                {
                    calculate.IncreManyTimes();
                });

                Task task2 = Task.Run(() =>
                {
                    calculate.IncreManyTimes();
                });
                Task.WaitAll(task1, task2);
            }).Wait();
           
            Console.WriteLine(calculate.Val);

            Console.ReadKey();
        }
    }
}

The related question: Does locking ensure reads and writes are flushed from caches? If so, how?

And my question could be described as: Does SemaphoreSlim(1, 1) ensure reads and writes are flushed from caches?

over 4 years ago · Santiago Trujillo
2 Respostas
Responde à pergunta

0

The parameters in the semaphoreslim specify how many threads can operate concurrently and what the initial count is. If you want to use semaphoreslim as the equivalent of the c# lock statement, then the number of supported threads must be one. When you initialize your sempahore with 10, you're saying that up to 10 threads can execute at the same time, which is not the same thing as a lock.

Semaphore has nothing to do with flushing reads or writes, to that is entirely based on how you use the semaphore.

If you're going to use it as a lock, you need to be sure that every time the semaphore is waited, it is also released, so use a try/finally block.

over 4 years ago · Santiago Trujillo Relatório

0

does the _semaphore has the same effect as lock?

Yes and no. Considering the behavior of your IncreManyTimes method it has the same effect indeed (_val = _val + 1; will not run concurrently by multiple threads).

They have some differences, though. For example, lock is always dedicated to its executing thread, whereas the SemaphoreSlim can be released from any thread. That's why a SemaphoreSlim is a good alternative for 'locking' around a code block that contains an await (which wouldn't even compile with lock because it would not work as intended if the continuation executes on a different thread).

As a further note, if there is an exception inside the lock, the lock is released. To achieve the same effect you must put your _semaphore.Release(); in a finally block.

Additionally, the SemaphorSlim is a disposable object so you should consider implementing IDisposable in your Calculate class.

And finally, I don't know if this is just a simplified example but here you don't need any of those. You can increment simply by Interlocked.Increment(ref _val), which does not need locking.

Edit:

Does SemaphoreSlim(1, 1) still ensures that I have the correct output 1000000, even if task1 and task2 run on 2 different cpu cores?

Yes, because it allows only one thread in the critical section at once.

over 4 years ago · Santiago Trujillo Relatório
Responde à pergunta
Encontrar trabalhos remotos

Descubra a nova forma de encontrar um emprego!

melhores empregos
Principais categorias de trabalho
Empresas
Postar vaga Preços Comercial
Jurídico
Termos e Condições Política de privacidade
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomende algumas ofertas para mim
Preciso de ajuda